前言:由于不可抗拒因素,初始的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!=' ') //检测字符串结束标志
{
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!
"); 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!=' ') //检测字符串结束标志
{
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!
");
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;
}
}
}
初步构想是首先通过模块与电脑,单片机与电脑通过串口的接受与发送进行调试,然后逐步过渡到单片机与模块直接的通信。