ATMEGA128 PWM输出系列例程

发布者:Meshulun最新更新时间:2017-11-20 来源: eefocus关键字:ATMEGA128  PWM输出 手机看文章 扫描二维码
随时随地手机看文章

1、定时器0,快速PWM模式

快速PWM可以的到比较高频率的PWM输出,但占空比的调节精度稍微差一些。此时计数器仅工作在单程正向计数方式,计数器的上限值决定PWM的频率,而比较匹配寄存器的值决定了占空比的大小。PWM频率的计算公式为:

PWM频率 = 系统时钟频率/(分频系数*(1+计数器上限值))

快速PWM模式适合要求输出PWM频率较高,但频率固定,占空比调节精度要求不高的应用。






#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的相位也相应的跟着变化。






#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波形输出


#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<#define SS_L() PORTB&=~(1<//注意,不要漏掉了()
#define led0_en() {DDRB|=1<<4;PORTB|=(1<<4);} //开第一个数码管的位选
#define led0_dis() {DDRB|=1<<4;PORTB&=~(1<<4);} //关第一个数码管的位选
#define led1_en() {DDRB|=1<<5;PORTB|=(1<<5);}
#define led1_dis() {DDRB|=1<<5;PORTB&=~(1<<5);}
#define led2_en() {DDRB|=1<<6;PORTB|=(1<<6);}
#define led2_dis() {DDRB|=1<<6;PORTB&=~(1<<6);}
#define led3_en() {DDRB|=1<<7;PORTB|=(1<<7);}
#define led3_dis() {DDRB|=1<<7;PORTB&=~(1<<7);}
#define OE 7
#define point 4
#define dp 7
#include
#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
delay_1us();
}

void delay_1ms(void) //1ms延时函数
{
unsigned int i;
for (i=0;i<1140;i++);
}

void delay_nms(unsigned int n) //N ms延时函数
{
unsigned int i=0;
for (i=0;i
delay_1ms();
}

void spi_init(void)
{
DDRB |= (1<SPCR = (1<}

void SPI_MasterTransmit(char Data)
{

SPDR = Data;

while(!(SPSR & (1<;
}

void HC_595_init(void)
{
DDRC |= (1<PORTC &= (1<PORTB = 0x0F; //同时打开四个数码管的位选
spi_init();
led_buffer[0]=16; //初始化数码管段码
led_buffer[1]=16;
led_buffer[2]=16;
led_buffer[3]=16;
}

void HC_595_OUT(unsigned char data)
{
SS_L();
SPI_MasterTransmit(data);
SS_H();
}
void leddis_update(void)
{

if(point==0)
HC_595_OUT(table[led_buffer[3]]|(1<else
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<else
HC_595_OUT(table[led_buffer[2]]);
led1_en();
delay_nus(60);
led1_dis();

if(point==2)
HC_595_OUT(table[led_buffer[1]]|(1<else
HC_595_OUT(table[led_buffer[1]]);
led2_en();
delay_nus(60);
led2_dis();


if(point==3)
HC_595_OUT(table[led_buffer[0]]|(1<else
HC_595_OUT(table[led_buffer[0]]);
led3_en();
delay_nus(60);
led3_dis();
}
void display_led(unsigned int data)
{
if(data>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]=(data00)/100;
led_buffer[2]=(data0)/10;
led_buffer[3]=data;
leddis_update();
}

else if(data>99)
{
led_buffer[0]=16; //关闭最高位的那个数码管
led_buffer[1]=(data00)/100;
led_buffer[2]=(data0)/10;
led_buffer[3]=data;
leddis_update();
}

else if(data>9)
{
led_buffer[0]=16;
led_buffer[1]=16;
led_buffer[2]=(data0)/10;
led_buffer[3]=data;
leddis_update();
}
else
{
led_buffer[0]=16;
led_buffer[1]=16;
led_buffer[2]=16;
led_buffer[3]=data;
leddis_update();
}


}
void init_devices(void)
{
port_init(); //端口初始化
HC_595_init(); //595初始化
}

main.c文件:


#include
#include "display.h"
#define uchar unsigned char
#define uint unsigned int
uint num;


void delay_ms(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=1140;y>0;y--);
}
void init_key()
{
DDRD=0X00;
PORTD=0XFF;
}

void keyscan(void )
{
if((PIND&0x01)==0)
{
while(!(PIND&0x01)); //松手检测
delay_ms(50);
num+=20;

if(num>=512)
num=0;
}
if((PIND&0x02)==0)
{
while(!(PIND&0x02));
delay_ms(50);
num-=20;
if(num<=0)
num=0;
}
if((PIND&0x08)==0)
{
while(!(PIND&0x01));
delay_ms(50);
num=256;
}
}


int main ()
{
uint temp;
init_key();
init_devices();
TCCR3A=0xff; //通道A,B,C均设置为比较输出模式
TCCR3B=0x0A; //采用10位快速PWM模式,top值为0X03FF,决定pwm频率;
TCNT3=0X0000; //设置定时器3的初始值
TIMSK=0X00;
ETIMSK=0X00;
DDRE=0xff;
num=256;
while(1)
{
//OCR3A=512; //决定OCR3A的占空比
keyscan();
OCR3B=num; //决定OC3B的占空比
temp=num*100/1023;
display_led(temp);

}
}


关键字:ATMEGA128  PWM输出 引用地址:ATMEGA128 PWM输出系列例程

上一篇:AVR定时器比较中断
下一篇:AVR单片机GCC编程:定时器的基本操作

推荐阅读最新更新时间:2024-03-16 15:46

STM32_TIM输出PWM波形
前言 今天讲解“STM32F103 TIM输出PWM波形”,提供的软件工程支持最大输出18MHz的PWM波形,函数接口只有两个参数:频率Freq 和 占空比Dutycycle。 定时器的功能很强大,今天讲解的PWM属于定时器中比较输出的功能,难度算一般吧(懂了的人决定很简单),因为使用了比较的功能。 PWM在实际应用中特别广泛,可能在校的学生不是很了解,但对于很多工作的人来说PWM的应用基本上遍布整个电子化的时代。对于电子相关专业的学生来说,信号发生器都不陌生,信号发生器就是PWM典型的应用。 本文特点:1.提供讲解的软件工程; 2.图片代码比直接贴出源代码容易阅读。 本着免费分享的原则,将讲解的工程源代码分享给大家,
[单片机]
STM32_TIM<font color='red'>输出</font><font color='red'>PWM</font>波形
msp430输出PWM
MSP430单片机的定时器除了可以捕获,比较之外,还可以作为PWM波产生器直接在芯片内部联通IO口。在官方手册上就有: Timer_B7 is a 16-bit timer/counter with seven capture/compare registers. Timer_B7 can support multiple capture/compares, PWM outputs, and interval timing. Timer_B7 also has extensive interrupt capabilities. Interrupts may be generated from the counter on ov
[单片机]
msp430<font color='red'>输出</font><font color='red'>PWM</font>波
ATMEGA128单片机定时器+数码管显示
#define SS 0 #define SCK 1 #define MOSI 2 #define MISO 3 #define SS_H() PORTB|=(1 SS) #define SS_L() PORTB&=~(1 SS) //注意,不要漏掉了() #define led0_en() {DDRB|=1 4;PORTB|=(1 4);} //开第一个数码管的位选 #define led0_dis() {DDRB|=1 4;PORTB&=~(1 4);} //关第一个数码管的位选 #define led1_en() {DDRB|=1 5;PORTB|=(1 5);} #define led1_dis() {DDRB|=1 5;
[单片机]
【STM32电机方波】记录4——PWM输出配置
PWM生成原理: 通用定时器可以利用GPIO引脚进行脉冲输出,在配置为比较输出、PWM输出功能时,捕获/比较寄存器通用定时器可以利用GPIO引脚进行脉冲输出,在配置为比较输出、PWM输出功能时,捕获/比较寄存器TIMx_CCR被用作比较功能,下面把它简称为比较寄存器。 这里直接举例说明定时器的PWM输出工作过程:若配置脉冲计数器TIMx_CNT为向上计数,而重载寄存器TIMx_ARR被配置为N,即TIMx_CNT的当前计数值数值X在TIMxCLK时钟源的驱动下不断累加,当TIMx_CNT的数值X大于N时,会重置TIMx_CNT数值为0重新计数。 而在TIMxCNT计数的同时,TIMxCNT的计数值X会与比较寄存器TIMx_CCR
[单片机]
【STM32电机方波】记录4——<font color='red'>PWM</font><font color='red'>输出</font>配置
微控制器 PWM 如何输出更高效地驱动负载
  大多数微控制器至少有一个脉冲宽度调制 (PWM) 外设,以方波形式生成多个波形。这些 PWM 输出可用于驱动同步负载,例如机械系统中的步进电机和电源转换器的功率 MOSFET。对于这些负载,要使目标负载正常工作,PWM 波形必须精确同步,这一点非常重要。   如果 PWM 外设未经过仔细编程,它可能偶尔会在波形之间产生相位延迟,从而导致在波形边沿未正确对齐时失去同步。这些相位延迟将会降低负载的驱动效率,从而浪费功率并可能产生过多的热量。对于常见的 PWM 外设,可以启用或禁用某个 PWM,但同时会导致其他 PWM 输出发生相位延迟。   这对于小规格电池供电型物联网 (IoT) 应用而言尤其是个问题。在此类应用中,单个
[嵌入式]
微控制器 <font color='red'>PWM</font> 如何<font color='red'>输出</font>更高效地驱动负载
msp430g2553输出PWM
用msp430g2553的定时器timerA就可以实现PWM波,内容不难!设置下时钟源,定时器配置一下就可以了 仿真: 代码: TA1CTL:选时钟源,计数模式增 TA1CCR0(定时器寄存器)与频率有关; TA1CCR1(定时器寄存器)与占空比有关; TA1CCTL1:OUTMOD_7输出模式选择。 #include msp430.h void main(void){ TA1CTL |= TASSEL_2 + MC_1; //选SMCLK,增计数 P2SEL |= BIT1; P2DIR |= BIT1;//P2.1设为输出TA1.1 TA1CCTL1 = OUTMOD_7; TA1CCR0 = 1115000/2
[单片机]
msp430g2553<font color='red'>输出</font><font color='red'>PWM</font>波
基于ATmega128单片机的智能蒸柜控制系统设计
智能蒸柜控制系统是一个蒸柜控制系统的改造与优化,之前采用的控制单元部件为西门子S5系列PLC和MP370触摸屏。S5系列模块已经停产,触摸屏操作也由于使用时间过长出现不灵敏现象,现使用的PLC模块与s5系列模块存在不兼容现象,并且PLC控制成本较高,故决定采用基于AVR单片机实现系统的节能优化。 1 系统简介 本次设计采用Atmel公司的AVR系列ATmega128单片,由于此单片机吸收了PLC及51单片机的优点,同PLC一样可以重设和复位;特别是AT mega128单片机具有128 KB FLASH,4 KB E2PROM,4 KB RAM,多达48个I/O,口,34个中断源,以及ISP下载及JTAG仿真口。CS5464
[单片机]
基于<font color='red'>ATmega128</font>单片机的智能蒸柜控制系统设计
STM32单片机学习---PWM输出
上午花了半天时间熟悉了stm32的PWM模块。中午利用午饭时间把PWM功能调试成功。当然,很简单的东西,也许很多前辈估计都不屑一顾的东西。 今天最大的感叹就是网络资源实在是个巨大的宝库,真的很庆幸,在这个复杂的社会环境里,在一个到处充斥着私心、私利的时代,各个网站,各个论坛上的众多网友都时刻保持着开源的氛围。学习一定要和他人交流,而网络提供了这么一个极好的平台。 废话少说,言归正传。 实现功能:采用定时器2的通道2,使PA1输出频率1K,占空比40的PWM波形,用PA8随意延时取反led灯,指示程序运行。 首先熟悉一下定时器的PWM相关部分。看图最明白 其实PWM就是定时器的一个比较功能而已。 CNT里的值不断++,一
[单片机]
STM32单片机学习---<font color='red'>PWM</font><font color='red'>输出</font>
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved