前言:由於不可抗拒因素,初始的STC12C5A60S2芯片由於無法進行燒錄(。。。因為沒帶有鎖緊座的開發板),暫且使用STC15F2K60S2芯片。。
一 串行通信概述:
串口通信有SPI IIC UART 等多種,最常見的是UART ,大部分情況下,串口通信指的就是UART.
- 關於波特率:串口每秒鍾傳輸的位數
- UART 的數據發送與接收:
- 串口有兩個緩沖寄存器SBUF,一個是發送寄存器,一個是接收寄存器,在物理結構上是完全獨立的,他們都是字節尋址的寄存器。
- 串行發送時,CPU向SBUF 寫入數據,例如SBUF=0x58;此時TI置1。
- 串行接收時,CPU從SBUF 讀出數據,例如Date=SBUF;此時RI置1。
二 代碼
1.初始化
可利用STC-ISP計算生成波特率等初始化數據。
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位數據,可變波特率
AUXR |= 0x40; //定時器1時鍾為Fosc,即1T
AUXR &= 0xFE; //串口1選擇定時器1為波特率發生器
TMOD &= 0x0F; //清除定時器1模式位
TMOD |= 0x20; //設定定時器1為8位自動重裝方式
TL1 = 0xDC; //設定定時初值
TH1 = 0xDC; //設定定時器重裝值
ET1 = 0; //禁止定時器1中斷
TR1 = 1; //啟動定時器1
EA=1; //打開總中斷
ES=1; //打開接收中斷
}
注意:初始化函數STC-ISP沒有生成總中斷和接收中斷,所以EA,ES注意補上。
2.中斷
void Usart() interrupt 4 //串口中斷函數接收程序
{
if (RI==1)
{
receiveData = SBUF;
RI=0;
}
}
串口中斷號如下:根據串口中斷選取中斷號。
中斷源 中斷號
外部中斷0 INT0 interrupt 0
定時器0中斷 T0 interrupt 1
外部中斷1 INT1 interrupt 2
定時器1中斷 T1 interrupt 3
串口中斷 TX/RX interrupt 4
如果接收到數據,將數據存儲到變量receiveData中,同時記得要軟件將RI置0。
以上單片機可以接收到發來的數據,那么單片機如何發送數據呢?
3.數據發送
void send1_Byte(unsigned char byte)//發送hex字符
{
SBUF = byte;
while(TI==0); //發送完會自動置1
TI=0; //手動清零
}
void Send1_String(char *str) //發送字符串
{
while (*str!='\0') //檢測字符串結束標志
{
send1_Byte(*str++);
}
}
第一個函數是單片機發送hex字符,第二個是單片機發送一個字符串。
當單片機發送結束后,TI會硬件置1,用此可以判斷是否發送結束,同時,發送結束后記得用軟件置0。
發送字符串同理。
4.具體功能的實現
因為考慮到將來單片機外接的模塊較多,所以通過串口(模擬各模塊)發送不同的數據給單片機,從而使單片機產生不同的功能。
void working()
{
if(receiveData!=0x00)//發現有數據輸入到單片機
{
switch(receiveData)
{
case 0x01: send1_Byte(11); receiveData=0x00; break;
case 0x02: send1_Byte(22); receiveData=0x00; break;
case 0x03: Send1_String("HELP!\r\n"); receiveData=0x00; break;
case 0x04: yy=1; receiveData=0x00; break;
}
}
}
int main()
{
uchar tt;
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
UartInit();
while(1)
{
working();
while(yy==1)
{
for(tt=0;tt<5;tt++)//led燈閃爍5次,表示提醒。
{
P0=0x00;
Delay500ms();
P0=0xff;
Delay500ms();
}
yy=0;
}
}
}
當發送0x01,0x02,0x03,0x04時,產生不同的效果。當串口發送0x03時,單片機會發送字符串“HELP!”,同理也可以增加更多功能。
三 總結
#include <stc15f2k60s2.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar receiveData,m,yy;
void UartInit(void) //9600bps@11.0592MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位數據,可變波特率
AUXR |= 0x40; //定時器1時鍾為Fosc,即1T
AUXR &= 0xFE; //串口1選擇定時器1為波特率發生器
TMOD &= 0x0F; //清除定時器1模式位
TMOD |= 0x20; //設定定時器1為8位自動重裝方式
TL1 = 0xDC; //設定定時初值
TH1 = 0xDC; //設定定時器重裝值
ET1 = 0; //禁止定時器1中斷
TR1 = 1; //啟動定時器1
EA=1; //打開總中斷
ES=1; //打開接收中斷
}
void send1_Byte(unsigned char byte)//發送hex字符
{
SBUF = byte;
while(TI==0); //發送完會自動置1
TI=0; //手動清零
}
void Send1_String(char *str) //發送字符串
{
while (*str!='\0') //檢測字符串結束標志
{
send1_Byte(*str++);
}
}
void Usart() interrupt 4 //串口中斷函數接收程序
{
if (RI==1)
{
receiveData = SBUF;
RI=0;
}
}
void working()
{
if(receiveData!=0x00) //發現有數據輸入
{
switch(receiveData)
{
case 0x01: send1_Byte(11);receiveData=0x00;break;
case 0x02: send1_Byte(22);receiveData=0x00;break;
case 0x03:
{
Send1_String("HELP!\r\n");
receiveData=0x00;
}
break;
case 0x04:
{
yy=1;
receiveData=0x00;
}
break;
}
}
}
void Delay500ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 22;
j = 3;
k = 227;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
int main()
{
uchar tt;
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF;
UartInit();
while(1)
{
working();
while(yy==1)
{
for(tt=0;tt<5;tt++)
{
P0=0x00;
Delay500ms();
P0=0xff;
Delay500ms();
}
yy=0;
}
}
}
初步構想是首先通過模塊與電腦,單片機與電腦通過串口的接受與發送進行調試,然后逐步過渡到單片機與模塊直接的通信。
