[英]Porting FreeRTOS to Arduino MEGA 2560 Rev3 (ATmega2560)
[英]Programming a PWM in an Arduino Mega ATmega2560 micro-controller
我正在尝试在Arduino Mega ( ATmega2560 )上启用PWM ,但我遇到了一些问题。
首先,我正试图在Ada中编程。 我希望将三个Timer3通道与FastPWM一起使用,所以我写道
procedure Main is
begin
-- Nullify Timer3 buffers
TCCR3A := 0;
TCCR3B := 0;
TCCR3C := 0;
-- Waveform Generation Mode
-- Fast PW, 8-bit, TOP = 0x00FF, Update OCR3x at BOTTOM, TOV3 Flag Set on TOP
-- => WGM33|WGM32|WGM31|WGM30 = 0|1|0|1
TCCR3A := TCCR3A or TCCR3A_WGM30;
TCCR3B := TCCR3B or TCCR3B_WGM32;
-- Compare Output Mode:
-- Fast PWM, non-inverting mode
-- => COM3A1|COM3A0|COM3B1|COM3B0|COM3C1|COM3C0 = 1|0|1|0|1|0
TCCR3A := TCCR3A or TCCR3A_COM3A1 or TCCR3A_COM3B1 or TCCR3A_COM3C1;
-- Clock Select: clk/1024 => CS32|CS31|CS30 = 1|1|1
TCCR3B := TCCR3B or TCCR3B_CS32 or TCCR3B_CS31 or TCCR3B_CS30;
-- Set Timer3 pins as output :
-- Channel A : Digital Pin 5 / Chip Pin 5 (PE3/OC3A/AIN1)
-- Channel B : Digital Pin 2 / Chip Pin 6 (PE4/OC3B/INT4)
-- Channel C : Digital Pin 3 / Chip Pin 7 (PE5/OC3C/INT5)
DDRE := DDRE_DDE3 or DDRE_DDE4 or DDRE_DDE5;
OCR3AH := 0;
OCR3AL := 250;
OCR3BH := 0;
OCR3BL := 250;
OCR3CH := 0;
OCR3CL := 250;
end Main;
硬件连接正常; 我在Arduino IDE上使用简单代码测试了它。 所以对我而言,很明显代码缺少某些东西或出错了,这应该是由PWM初始化问题引起的。 有人可以解释一下我在哪里犯了这样的错误吗?
提前致谢。
更新
如果Ada很难得到整个逻辑,那么C中的等效代码就是(你可以使用AS6构建它,结果是相同的,即没有生成信号):
int main(void){
TCCR3A = 0;
TCCR3B = 0;
TCCR3C = 0;
/* Waveform Generation Mode
Fast PW, 8-bit, TOP = 0x00FF, Update OCR3x at BOTTOM, TOV3 Flag Set on TOP
=> WGM33|WGM32|WGM31|WGM30 = 0|1|0|1 */
TCCR3A = TCCR3A|(1<<WGM30);
TCCR3B = TCCR3B|(1<<WGM32);
/* Compare Output Mode:
Fast PWM, non-inverting mode
=> COM3A1|COM3A0|COM3B1|COM3B0|COM3C1|COM3C0 = 1|0|1|0|1|0*/
TCCR3A = TCCR3A|(1<<COM3A1)|(1<<COM3B1)|(1<<COM3C1);
/* Clock Select: clk/1024 => CS32|CS31|CS30 = 1|1|1 */
TCCR3B = TCCR3B|(1<<CS32)|(1<<CS31)|(1<<CS30);
/* Set Timer3 pins as output :
Channel A : Digital Pin 5 / Chip Pin 5 (PE3/OC3A/AIN1)
Channel B : Digital Pin 2 / Chip Pin 6 (PE4/OC3B/INT4)
Channel C : Digital Pin 3 / Chip Pin 7 (PE5/OC3C/INT5)*/
DDRE = DDRE|(1<<DDE3)|(1<<DDE4)|(1<<DDE5);
/* Set PWM Duty Cycles */
OCR3AH = 0;
OCR3AL = 250;
OCR3BH = 0;
OCR3BL = 250;
OCR3CH = 0;
OCR3CL = 250;
}
查看www.atmel.com/Images/doc2549.pdf第136页,我看到一个注释:
“必须将第57页上的”PRR1 - 功耗降低寄存器1“中的功耗降低定时器/计数器3位PRTIM3写入零,以使能T / C模块。”
可能相关吗?
我不知道电源管理注册表的默认值是什么,我还没有使用2560。
其余的看起来还不错,虽然我在328p上使用了定时器库avr-timer0.adb等而不是自己滚动。
我不确定,但是如果你在主函数结束时忘记了无限循环,程序就会停止,所有中断都将被禁用,控制器进入一个空循环。
没有中断就没有PWM。
int main(void){
....
while (1) {
}
return 0;
}
您需要在SREG中设置SEI标志以启用中断并在main中添加无限循环。 Avr程序在到达主函数结束后不会终止或挂起,但会重新开始。 http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_SEI.html
一个观察结果突然出现 - 几乎可以肯定这是不对的:
-- => COM3A1|COM3A0|COM3B1|COM3B0|COM3C1|COM3C0 = 1|0|1|0|1|0
TCCR3A := TCCR3A or TCCR3A_COM3A1 or TCCR3A_COM3B1 or TCCR3A_COM3C1;
为什么? 因为像COM3A0
这样的命名常量只是指示位位置(0到7)的整数的别名。 在C中,当我们设置这些时,我们执行以下操作:
REGISTER |= (1<<COM3A0);
并且COM3A0 = 3,然后它变为(1 << 3),或8为ORed。
在将其与当前寄存器值进行“或”运算之前,向左移动1个位置。 因此,除非您的COM3A0已经进行了位移,否则所有这些语句都是对几个1和0进行OR运算并将单个结果分配给TCCR3A。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.