做了一個實例,以前都是用AVR直接硬件生成PWM,方便快捷,幾條語句的問題,驅動能力還強,從來沒仔細想過如何用51單片機軟件方法做一個,現在非要用51單片機做,那就直接開始制作,首先硬件焊接,軟件編程,只說程序部分,程序采用占空比可調,頻率可調的思路,需要用到2個定時器,1個定時器輸出占空比信號數據,另個定時器標定頻率,具體的程序稍后放出,其實也不太難,問題1:如何做到定時器內的軟件時間低于定時器定時中斷時間 ,頻率低無所謂,頻率要是到了20khz,這個問題就有些困難,有些if語句進入循環后可以到20ms,這個問題解決采用51單片機特有的中斷嵌套解決。
問題2 :如何做到外部中斷、定時器0、定時器1中斷優先級分級?解決方法就是分別在各自的服務程序中處理好中斷優先級。
視頻:
視頻演示的僅僅是占空比的變化,題目為:基于51單片機的出租車計價器設計(霍爾元件版本+減速、等待計時等功能)
=============
以下測試程序為版本V1.0的測試程序,非視頻中的程序,沒有加入PWM控制,只是脈沖檢測部分的。
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit cs1=P1^0;
sbit cs2=P1^1;
sbit cs3=P1^2;
sbit cs4=P1^3;
sbit start=P2^1;
sbit turn=P2^0;
uint s,n=500;
uint m=500;
bit val=0;
bit flag=0;
uchar code tab[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90
};
uchar code tabpoint[]={
0x40,0x79,0x24,0x30,
0x19,0x12,0x02,0x78,
0x00,0x10
};
void delay(uint ms)
{
uint i,j;
for (i=ms;i>0;i--)
for (j=110;j>0;j--);
}
void delayus(uint us)
{
while(--us);
}
void displayday()
{
P0=tab[n/1000];
cs1=0;
delayus(20);
cs1=1;
P0=0xff;
P0=tabpoint[n%1000/100];
cs2=0;
delayus(20);
cs2=1;
P0=0xff;
P0=tab[n%100/10];
cs3=0;
delayus(20);
cs3=1;
P0=0xff;
P0=tab[n%10];
cs4=0;
delayus(20);
cs4=1;
P0=0xff;
}
void displaynight()
{
P0=tab[m/1000];
cs1=0;
delayus(20);
cs1=1;
P0=0xff;
P0=tabpoint[m%1000/100];
cs2=0;
delayus(20);
cs2=1;
P0=0xff;
P0=tab[m%100/10];
cs3=0;
delayus(20);
cs3=1;
P0=0xff;
P0=tab[m%10];
cs4=0;
delayus(20);
cs4=1;
P0=0xff;
}
void displayoff()
{
P0=0xff;
cs1=cs2=cs3=cs4=0;
}
void main()
{
TMOD=0x02;
TH0=(256-1)/256;
TL0=(256-1)%256;
EA=1;
ET0=1;
TR0=1;
EX0=1;
IT0=0;
while(1)
{
if (start==0&&flag==0)
{
displayday();
}
if (start==0&&flag==1)
{
displaynight();
}
if (start==1)
{
displayoff();
}
}
}
void jisuan() interrupt 0
{
s++;
delay(1);
if (val==1&&s==1000)
{
n=n+130;
m=m+200;
s=0;
if (n==9990)
{
n=0;
val=0;
}
if (m==9900)
{
m=0;
val=0;
}
}
if (s==3000)
{
val=1;
s=0;
}
}
void jiance() interrupt 1
{
if (turn==0)
{
delayus(20);
if (turn==0)
{
flag=!flag;
}
}
}