當前位置:首頁 > 單片機 > 單片機
[導讀]1、定時器0,快速PWM模式快速PWM可以的到比較高頻率的PWM輸出,但占空比的調(diào)節(jié)精度稍微差一些。此時計數(shù)器僅工作在單程正向計數(shù)方式,計數(shù)器的上限值決定PWM的頻率,而比較匹配寄存器的值決定了占空比的大小。PWM頻率

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

快速PWM可以的到比較高頻率的PWM輸出,但占空比的調(diào)節(jié)精度稍微差一些。此時計數(shù)器僅工作在單程正向計數(shù)方式,計數(shù)器的上限值決定PWM的頻率,而比較匹配寄存器的值決定了占空比的大小。PWM頻率的計算公式為:

PWM頻率 = 系統(tǒng)時鐘頻率/(分頻系數(shù)*(1+計數(shù)器上限值))

快速PWM模式適合要求輸出PWM頻率較高,但頻率固定,占空比調(diào)節(jié)精度要求不高的應用。






#include
#include
#define uint unsigned int
#define uchar unsigned char
volatile uchar num;

void pwm0_init(void)
{
DDRB=0X10; //將PB4設(shè)置為輸出
TCCR0=0X00; //關(guān)閉
num=64; //設(shè)置輸出比較寄存器的初值
TCNT0=0; //計數(shù)器初值為0
TCCR0=0X6A; //設(shè)置為快速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,相位修正(調(diào)整)模式

頻率(相位)調(diào)整PWM模式的占空比調(diào)節(jié)精度高,但輸出頻率比較低,因為此時計數(shù)器僅工作在雙向計數(shù)方式。同樣計數(shù)器的上限值決定了PWM的頻率,比較匹配寄存器的值決定了占空比的大小。PWM頻率的計算公式為:

PWM頻率 = 系統(tǒng)時鐘頻率/(分頻系數(shù)*2*計數(shù)器上限值))

相位調(diào)整PWM模式適合要求輸出PWM頻率較低,但頻率固定,占空比調(diào)節(jié)精度要求高的應用。當調(diào)整占空比時,PWM的相位也相應的跟著變化。






#include
#include
#define uint unsigned int
#define uchar unsigned char
volatile uchar num;

void pwm0_init(void)
{
DDRB=0X10; //將PB4設(shè)置為輸出,即OC0
TCCR0=0X00; //關(guān)閉
num=64; //設(shè)置輸出比較寄存器的初值
TCNT0=0; //計數(shù)器初值為0
TCCR0=0X62;//設(shè)置為相位調(diào)整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均設(shè)置為比較輸出模式
TCCR1B=0x0A; //采用10位快速PWM模式,top值為0X03FF,決定pwm頻率;
TCNT1=0X0000; //設(shè)置定時器的初始值
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波形,占空比可調(diào),數(shù)碼管顯示占空比,同時控制舵機轉(zhuǎn)動

需要注意的問題:

如果直接將輸出的pwm信號連接到舵機的信號輸入端,是不能夠驅(qū)動舵機的,必須有驅(qū)動電路,我用的是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);} //開第一個數(shù)碼管的位選
#define led0_dis() {DDRB|=1<<4;PORTB&=~(1<<4);} //關(guān)第一個數(shù)碼管的位選
#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延時函數(shù)
{
asm("nop");
}
void delay_nus(unsigned int n) //N us延時函數(shù)
{
unsigned int i=0;
for (i=0;i
delay_1us();
}

void delay_1ms(void) //1ms延時函數(shù)
{
unsigned int i;
for (i=0;i<1140;i++);
}

void delay_nms(unsigned int n) //N ms延時函數(shù)
{
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; //同時打開四個數(shù)碼管的位選
spi_init();
led_buffer[0]=16; //初始化數(shù)碼管段碼
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); //當計數(shù)大于9999時,四個數(shù)碼管同時輸出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; //關(guān)閉最高位的那個數(shù)碼管
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均設(shè)置為比較輸出模式
TCCR3B=0x0A; //采用10位快速PWM模式,top值為0X03FF,決定pwm頻率;
TCNT3=0X0000; //設(shè)置定時器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);

}
}


本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫毥谦F公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質(zhì)增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競爭力 堅持高質(zhì)量發(fā)展策略,塑強核心競爭優(yōu)勢...

關(guān)鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術(shù)學會聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(shù)(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉