1. 程式人生 > >基於51微控制器的pwm和串列埠通訊

基於51微控制器的pwm和串列埠通訊

此例程設定了按鍵可以調整100-1000hz的不同頻率(100的倍數)的方波,另外還加入了串列埠通訊,可以通過串列埠傳送來的數字來設定相對應的頻率;

#include <reg52.h>
#include"uart.h"

sbit PWMOUT = P1^0;
sbit led = P2^2;
sbit KEY1 = P1^2;
sbit KEY2 = P3^3;

unsigned char HighRH = 0;  //高電平過載值的高位元組
unsigned char HighRL = 0;  //高電平過載值的低位元組
unsigned char LowRH  = 0;  //低電平過載值的高位元組
unsigned char LowRL  = 0;  //低電平過載值的低位元組
unsigned int fr;
unsigned int k=0,t,i;
unsigned int s= 100;
unsigned char a[3];
unsigned int b=0;
   
void ConfigPWM(unsigned int fr, unsigned char dc);
void ConfigUART(unsigned int baud);
void delay(unsigned int n){ while (n--);}

void main()
{   
	bit backup1 = 1;
	bit backup2 = 1;
	bit keybuf1 = 1;  //按鍵值暫存,臨時儲存按鍵的掃描值
	bit keybuf2 = 1;  //按鍵值暫存,臨時儲存按鍵的掃描值
    //keybuf1 = KEY1;            //把當前掃描值暫存
	EA=1;
	led = 0;
    ConfigUART(9600);  //配置波特率為9600
	ConfigPWM(100,50);
	//Timer1Init();
    while (1)
    {
	  if(k==1)
	  {
	      k=0;
		  ConfigPWM(s,50);
	  	  led = ~led;delay(2000);
	  }

          	keybuf1 = KEY1;            //把當前掃描值暫存
          if (keybuf1 != backup1)     //當前值與前次值不相等說明此時按鍵有動作
          { 
            delay(1000);              //延時大約10ms
            if (keybuf1 == KEY1)   //判斷掃描值有沒有發生改變,即按鍵抖動
            {
               if (backup1 == 0)  //如果前次值為0,則說明當前是彈起動作
                  {
                    s = s-50;      
                }
                backup1 = keybuf1;  //更新備份為當前值,以備進行下次比較
            }
			ConfigPWM(s,50);
          }
		  keybuf2 = KEY2;            //把當前掃描值暫存
          if (keybuf2 != backup2)     //當前值與前次值不相等說明此時按鍵有動作
          {
            delay(1000);              //延時大約10ms
            if (keybuf2 == KEY2)   //判斷掃描值有沒有發生改變,即按鍵抖動
            {
                if (backup2 == 0)  //如果前次值為0,則說明當前是彈起動作
                {
                    s = s+50;      
                }
                backup2 = keybuf2;  //更新備份為當前值,以備進行下次比較
            }
			ConfigPWM(s,50);
          }
		   



	}
}

void ConfigUART(unsigned int baud)
{
    SCON  = 0x50;  //配置串列埠為模式1
    TMOD &= 0x0F;  //清零T1的控制位
    TMOD |= 0x20;  //配置T1為模式2
    TH1 = 256 - (11059200/12/32)/baud;  //計算T1過載值
    TL1 = TH1;     //初值等於過載值
	ET1 = 0;		//中斷T1
	ES = 1;			//串列埠中斷
    TR1 = 1;       //啟動T1
}

void ConfigPWM(unsigned int fr, unsigned char dc)
{
unsigned int high, low;
unsigned long tmp;
tmp = (11059200/12)/fr; //計算一個週期所需的計數值
high = (tmp*dc) / 100; //計算高電平所需的計數值
low = tmp -  high; //計算低電平所需的計數值
high = 65536 - high + 12; //計算高電平的過載值並補償中斷延時
low = 65536 - low + 12; //計算低電平的過載值並補償中斷延時
HighRH = (unsigned char)(high>>8); //高電平過載值拆分為高低位元組
HighRL = (unsigned char)high;
LowRH = (unsigned char)(low>>8); //低電平過載值拆分為高低位元組
LowRL = (unsigned char)low;
TMOD &= 0xF0; //清零 T0 的控制位
TMOD |= 0x01; //配置 T0 為模式 1
TH0 = HighRH; //載入 T0 過載值
TL0 = HighRL;
ET0 = 1; //使能 T0 中斷
TR0 = 1; //啟動 T0
PWMOUT = 1; //輸出高電平
}

void InterruptTimer0() interrupt 1
{
    if (PWMOUT == 1)  //當前輸出為高電平時,裝載低電平值並輸出低電平
    {
        TH0 = LowRH;
        TL0 = LowRL;
        PWMOUT = 0;
    }
    else              //當前輸出為低電平時,裝載高電平值並輸出高電平
    {
        TH0 = HighRH;
        TL0 = HighRL;
        PWMOUT = 1;
    }
}

/*void Timer1Init()
{
	TMOD|=0X10;//選擇為定時器1模式,工作方式1,僅用TR1開啟啟動。

	TH1=0XFC;	//給定時器賦初值,定時1ms
	TL1=0X18;	
	ET1=1;//開啟定時器1中斷允許
	EA=1;//開啟總中斷
	TR1=1;//開啟定時器			
}
void Timer1() interrupt 3
{
	static u16;
	TH1=0XFC;	//給定時器賦初值,定時1ms
	TL1=0X18;
	i++;
	if(i==1000)
	{
		i=0;
		t++;
		if(t%2==0)
		{
		   SBUF=t/10;
		   SBUF=t%10;
		}
	}	
}*/

void ComINT() interrupt 4	 //中斷接收程式
{	
	if(RI)			   //判斷是否接收完,接收完成後,由硬體置RI位
	{
	  RI=0;									 
	  //SBUF=SBUF;
	  a[b]=SBUF;
	  b++;
	   if(b==3)
	   {
	     /*if(a[0]=='a'&&a[1]=='b'&&a[2]=='c') 
		 {led = 0;delay(2000);}
		 else
		 {led = 1;}*/
	   	 b=0;s=(a[0]-0x30)*100+(a[1]-0x30)*10+(a[2]-0x30);
		  k=1;
		  //SBUF = 'T';
	   }  
}	  
if(TI)
{
	  TI=0;

	}
}