当前位置:首页 > 单片机 > 单片机
[导读]1、定时器0,快速PWM模式快速PWM可以的到比较高频率的PWM输出,但占空比的调节精度稍微差一些。此时计数器仅工作在单程正向计数方式,计数器的上限值决定PWM的频率,而比较匹配寄存器的值决定了占空比的大小。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);

}
}


本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

  日前,在日内瓦举行的国际电信联盟(ITU-T)第2研究组全会上,由大唐电信旗下大唐软件和中国电信共同主导制定的云计算标准“ITU-T M.3371:Requirements fo

关键字: atmega128 控制系统 移动机器人

随着艺术模型、机械加工、工装模具等产业的飞速发展,对加工设备提出的要求越来越高,雕刻机作为上述产业的重要组成部分也发生了快速的发展。目前,传统雕刻机体积大、操作

关键字: atmega128 单片机 数控雕刻 电源技术解析

首先是一些必要的声明#include#include"pwm.h"u32Sys_Clk=1000000;u16pwm1_2_Freqz;//pwm波1,2输出口的频率u16pwm3_4_Freqz;/...

关键字: pwm输出 STM32

图一图二PWM应用非常广泛,但是不同的项目对输出的PWM又有特殊要求,为满足这些要求我们需要更多的实验来验证。接下来讲述图一显示波形的输出方法步骤(图二为异常波形)。一、本实例所使用资源:1、TIM4_CH3(对应管脚

关键字: pwm输出 STM32 占空比 自定义频率

配置过程:(以TIM3为例,其CH1-CH4为:PA6、PA7、PB0、PB1)1)开启TIM3时钟,配置4个IO口为复用推挽输出。2)设置TIM3的ARR和PSC来控制PWM的周期。3)设置TIM3的CH1-CH4的P...

关键字: pwm输出 STM32 通用定时器

//环境:winavr+avr studiochar temp=0;ISR(TIMER1_COMPA_vect )//中断函数{ // user code here temp++; if (temp==10) temp=...

关键字: atmega128 定时器1

参考正点原子PWM输出MINI板输出实验。首先附PWM输出通道原子提供的代码只有一路PWM,但是定时器的配置已经无需更改了。我们需要修改PWM.c文件1.添加通道二的初始化TIM_OC2Init(TIM1,&TI...

关键字: pwm输出 stm32f103c8v6

#include "myuart.h"#include "avr/io.h"#include#define UDRE 5#define RXEN 4#define TXEN 3#d...

关键字: atmega128 uart

STM32 TIM8初始化的配置与通用定时器的配置不同,我最开始时按照通用定时器配置,无论是配置一个通道,还是配置所有通道,死活不出来pwm。接着查资料说要添加这一句代码:TIM_CtrlPWMOutputs(TIM8,...

关键字: pwm输出 STM32 tim8

#define SS 0#define SCK1#define MOSI 2#define MISO 3#define SS_H() PORTB|=(1

关键字: atmega128 单片机 定时器 数码管显示
关闭