1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
#include "analogio.h"
#define PWM_MAX_PINS 4
static int pwm_pin_num[PWM_MAX_PINS]; // PWM出力に使うピン番号を格納する
static int pwm_duty_value[PWM_MAX_PINS]; // それぞれのピンのデューティを格納する
static int pwm_already_inuse = 0; // すでに登録しているピンの数
static int pwm_init_done = 0;
//static int pwm_interrpt_loopnum[PWM_MAX_PINS]; // ユークリッドの互除法を使うので割り込み回数をカウント
void analogWrite(int pinnum, int value)
{
int i;
int pwm_using_num = -1; // PWMを割り当てているピン
if(pwm_init_done == 0)
{
setup_TIMER16_0();
setup_TIMER16_1();
pwm_init_done = 1;
}
for(i = 0; i < PWM_MAX_PINS; i++)
{
if(pwm_pin_num[i] == pinnum) // すでに登録されているピン
{ // デューティをセット
pwm_using_num = i;
pwm_duty_value[i] = value;
if(value == -1)pwm_already_inuse--;
break;
}
}
if(pwm_using_num == -1)//新規登録の場合
{
if(PWM_MAX_PINS > pwm_already_inuse) // まだ登録可能
{
for(i = 0; i < PWM_MAX_PINS; i++)
{
if((pwm_duty_value[i] == -1)&&(value != -1)) // 登録されていないピン
{
pwm_using_num = i;
pwm_pin_num[i] = pinnum; // ピン番号登録
pwm_duty_value[i] = value; // dutyセット
pwm_already_inuse++; // 使用中のピン数を+1
pinMode(pwm_pin_num[i],OUTPUT);
break;
}
}
}
}
switch(pwm_using_num)
{
case 0: LPC_TMR16B0->MR1 = pwm_duty_value[i]; break;
case 1: LPC_TMR16B0->MR2 = pwm_duty_value[i]; break;
case 2: LPC_TMR16B1->MR1 = pwm_duty_value[i]; break;
case 3: LPC_TMR16B1->MR2 = pwm_duty_value[i]; break;
default: break;
}
//pwm_eucledean_algorithm(pwm_using_pins);// 互除法演算ルーチンへ
return;
}
void pwm_eucledean_algorithm(int pwm_using_pins)
{
// reserved for future use.
}
//low level functions for software PWM
void setup_TIMER16_0(void)
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1U << 7);
// 1周期490Hzで分解能8bit => 約125kHz (125kHz = 48MHz / 382)
LPC_TMR16B0->PR = 382; // Pre-Scaler
LPC_TMR16B0->MR3 = 255; // Interval
LPC_TMR16B0->MR2 = 200;
LPC_TMR16B0->MR1 = 200;
// Interval Interrupt Operation
// Clear TC when MR3 match
// Interrupt when MR1 reset /MR2 reset /MR3 match
LPC_TMR16B0->MCR = ((3U << 9)|(1U << 6)|(1U << 3));
// Enable Interrupt
NVIC_EnableIRQ(TIMER_16_0_IRQn);
NVIC_SetPriority(TIMER_16_0_IRQn, 3);
// Start Timer
LPC_TMR16B0->TCR = 1;
for(int i = 0; i < PWM_MAX_PINS; i++) // まだ登録可能
{
pwm_duty_value[i] = -1; // 登録されていないピン
}
}
void setup_TIMER16_1(void)
{
LPC_SYSCON->SYSAHBCLKCTRL |= (1U << 8);
// 1周期490Hzで分解能8bit => 約125kHz (125kHz = 48MHz / 382)
LPC_TMR16B1->PR = 382; // Pre-Scaler
LPC_TMR16B1->MR3 = 255; // Interval
LPC_TMR16B1->MR2 = 200;
LPC_TMR16B1->MR1 = 200;
// Interval Interrupt Operation
// Clear TC when MR3 match
// Interrupt when MR1 reset /MR2 reset /MR3 match
LPC_TMR16B1->MCR = ((3U << 9)|(1U << 6)|(1U << 3));
// Enable Interrupt
NVIC_EnableIRQ(TIMER_16_1_IRQn);
NVIC_SetPriority(TIMER_16_1_IRQn, 3);
// Start Timer
LPC_TMR16B1->TCR = 1;
}
//===========================
// Timer16 Interrupt Handler
//===========================
void TIMER16_0_IRQHandler(void)
{
if (LPC_TMR16B0->IR & (1U << 1)) //MR1INT = case0
{
//Do something
if(pwm_duty_value[0] != -1) digitalWrite(pwm_pin_num[0],LOW);
// Clear Flag
LPC_TMR16B0->IR = (1U << 1);
}
if (LPC_TMR16B0->IR & (1U << 2)) //MR2INT = case1
{
//Do something
if(pwm_duty_value[1] != -1) digitalWrite(pwm_pin_num[1],LOW);
// Clear Flag
LPC_TMR16B0->IR = (1U << 2);
}
// Timer16_1
if (LPC_TMR16B1->IR & (1U << 1)) //MR1INT = case0
{
//Do something
if(pwm_duty_value[2] != -1) digitalWrite(pwm_pin_num[2],LOW);
// Clear Flag
LPC_TMR16B1->IR = (1U << 1);
}
if (LPC_TMR16B1->IR & (1U << 2)) //MR2INT = case1
{
//Do something
if(pwm_duty_value[3] != -1) digitalWrite(pwm_pin_num[3],LOW);
// Clear Flag
LPC_TMR16B1->IR = (1U << 2);
}
if(LPC_TMR16B0->IR & (1U << 3)) //MR3INT
{
if(pwm_duty_value[0] > 1) digitalWrite(pwm_pin_num[0],HIGH);
if(pwm_duty_value[1] > 1) digitalWrite(pwm_pin_num[1],HIGH);
// Clear Flag
LPC_TMR16B0->IR = (1U << 3);
}
//Timer1
if(LPC_TMR16B1->IR & (1U << 3)) //MR3INT
{
//Do something
if(pwm_duty_value[2] > 1) digitalWrite(pwm_pin_num[2],HIGH);
if(pwm_duty_value[3] > 1) digitalWrite(pwm_pin_num[3],HIGH);
// Clear Flag
LPC_TMR16B1->IR = (1U << 3);
}
}
void TIMER16_1_IRQHandler(void)
{
TIMER16_0_IRQHandler();
}
|