logo资料库

ATmega128 AVR单片机PWM输出教程附带详细程序说明.pdf

第1页 / 共11页
第2页 / 共11页
第3页 / 共11页
第4页 / 共11页
第5页 / 共11页
第6页 / 共11页
第7页 / 共11页
第8页 / 共11页
资料共11页,剩余部分请下载后查看
ATMEGA128 PWM 输出系列例程 1、定时器 0,快速PWM模式 快速 PWM 可以的到比较高频率的 PWM 输出,但占空比的调节精度稍微差一些。此时计数器仅工作在单程正向计数方式,计数器的上限值决定 PWM 的频率, 而比较匹配寄存器的值决定了占空比的大小。PWM 频率的计算公式为: PWM频率 = 系统时钟频率/(分频系数*(1+计数器上限值)) 快速 PWM 模式适合要求输出 PWM 频率较高,但频率固定,占空比调节精度要求不高的应用。 /*定时器 0,快速 PWM 模式,由 OC0 输出 PWM 波 */ /*PWM 频率 = 系统时钟频率/(分频系数*(1+计数器上限值))*/ /*本程序中:频率=8000000/(8*(1+255))=3.91KHZ,频率固定 */ /*占空比为:OCR0/0XFF=OCR0/256,占空比可调 */ /*TCNT0 从 BOTTOM 计数到 MAX,然后回到 BOTTOM 重新开 始;TCNT0 计数到与 OCR0 相等时, OC0 清零,在 BOTTOM 时置位 1 */ #include #include #define uint unsigned int #define uchar unsigned char volatile uchar num; void pwm0_init(void) { DDRB=0X10; //将 PB4 设置为输出 TCCR0=0X00; //关闭 num=64; //设置输出比较寄存器的初值 TCNT0=0; //计数器初值为 0 TCCR0=0X6A; //设置为快速 pwm 模式,采取 8 分频 } /*键盘初始化 */ void init_key() { DDRD=0X00; PORTD=0XFF; } /*延时函数 */
void delay_ms(uint z) { uint x,y; for(x=z;x>0;x--) for(y=1140;y>0;y--); } /*键盘扫描 */ void keyscan(void ) { if((PIND&0x01)==0) { while(!(PIND&0x01)); //松手检测 delay_ms(50); num+=5; if(num==255) num=0; } if((PIND&0x02)==0) { while(!(PIND&0x02)); delay_ms(50); num-=5; if(num==0) num=255; } if((PIND&0x08)==0) { while(!(PIND&0x01)); delay_ms(50); num=128; } } void main(void) { uchar wide; pwm0_init(); init_key(); while(1) { OCR0=num; keyscan(); } }
2、定时器 0,相位修正(调整)模式 频率(相位)调整 PWM 模式的占空比调节精度高,但输出频率比较低,因为此时计数器仅工作在双向计数方式。同样计数器的上限值决定了 PWM 的频率, 比较匹配寄存器的值决定了占空比的大小。PWM 频率的计算公式为: PWM频率 = 系统时钟频率/(分频系数*2*计数器上限值)) 相位调整 PWM 模式适合要求输出 PWM 频率较低,但频率固定,占空比调节精度要求高的应用。当调整占空比时,PWM 的相位也相应的跟着变化。 /*定时器 0,相位调整 PWM 模式,由 OC0 输出 PWM 波 */ /*PWM 频率 = 系统时钟频率/(分频系数*(1+2*计数器上限值)) */ /*本程序中:频率=8000000/(8*(1+2*255))=1.96KHZ,频率固定 */ /*占空比为:OCR0/0XFF=OCR0/256,占空比可调 */ /*TCNT0 从 BOTTOM 递增计数到 MAX,然后递减计数回到 BOTTOM,再从 BOTTOM 重新开始,以此往复;TCNT0 增计数到 与 OCR0 相等时,OC0 清零;TCNT0 减计数到 OCR0 时,OC0 置 1 */ #include #include #define uint unsigned int #define uchar unsigned char volatile uchar num; void pwm0_init(void) { DDRB=0X10; //将PB4 设置为输出,即OC0 TCCR0=0X00; //关闭 num=64; //设置输出比较寄存器的初值 TCNT0=0; //计数器初值为 0 TCCR0=0X62; //设置为相位调整PWM模式,8 分频 } /*键盘初始化 */ void init_key() { DDRD=0X00; PORTD=0XFF; } /*延时函数 */ void delay_ms(uint z) { uint x,y; for(x=z;x>0;x--) for(y=1140;y>0;y--); }
/*键盘扫描 */ void keyscan(void ) { if((PIND&0x01)==0) { while(!(PIND&0x01)); //松手检测 delay_ms(50); num+=5; if(num==255) num=0; } if((PIND&0x02)==0) { while(!(PIND&0x02)); delay_ms(50); num-=5; if(num==0) num=255; } if((PIND&0x08)==0) { while(!(PIND&0x01)); delay_ms(50); num=128; } } void main(void) { uchar wide; pwm0_init(); init_key(); while(1) { OCR0=num; keyscan(); } } 3、定时器 1pwm波形输出 /*====================================================== 使用定时器 1,OCR1A,OCR1B,OCR1C 三个管脚同时输出 PWM 波形 在快速 PWM 的模式下,top=0x03ff=1023
OCRnX 在 top 时刻更新 频率=8000000/8/1023=977.5HZ =======================================================*/ #include int main () { unsigned int i,a=0,c=0; unsigned char b=0; TCCR1A=0xff; //通道 A,B,C 均设置为比较输出模式 TCCR1B=0x0A; //采用 10 位快速 PWM 模式,top 值为 0X03FF,决定 pwm 频率; TCNT1=0X0000; //设置定时器的初始值 TIMSK=0X00; ETIMSK=0X00; DDRB=0xff; while(1) { OCR1A=512; //决定 OCR1A 的占空比 OCR1B=256; //决定 OC1B 的占空比 OCR1C=OCR1C+1; //决定 OC1C 的占空比 c++; OCR1C=c; if(c>=0x03f0) {c=0;}; i=500; while(i--); } } 4、定时器 3,OCRB3 输出PWM波形,占空比可调,数码管显示占 空比,同时控制舵机转动 需要注意的问题: 如果直接将输出的pwm信号连接到舵机的信号输入端,是不能够驱动舵机的,必须有驱动电路, 我用的是TLP281-4 进行光耦隔离。 舵机的三根线依次为:地线(棕色),电源线(红色),信号线(黄色),当然不同的舵机,可能 有所不同。 display.h文件: #define SS 0 #define SCK 1 #define MOSI 2 #define MISO 3
#define SS_H() PORTB|=(1< #include void port_init (void) { DDRA=0XFF; PORTA=0XFF; } const unsigned char table[]={0x3F,0x06,0x5B,0x4F,0x66, //0,1,2,3,4 0x6D,0x7D,0x07,0x7F,0x6F, //5,6,7,8,9 0x77,0x7C,0x39,0x5E,0x79,0x71,0x00}; //a,b,c,d,e,f volatile unsigned char led_buffer[4]; void delay_1us(void) //1us 延时函数 { asm("nop"); } void delay_nus(unsigned int n) //N us 延时函数 { unsigned int i=0; for (i=0;i
unsigned int i=0; for (i=0;i
HC_595_OUT(table[led_buffer[3]]); led0_en(); delay_nus(60); led0_dis(); if(point==1) HC_595_OUT(table[led_buffer[2]]|(1<9999) { HC_595_OUT(0xFF); //当计数大于 9999 时,四个数码管同时输出 8 PORTB|=((1<<4)|(1<<5)|(1<<6)|(1<<7)); } else if(data>999) { led_buffer[0]=data/1000; led_buffer[1]=(data%1000)/100; led_buffer[2]=(data%100)/10; led_buffer[3]=data%10;
分享到:
收藏