使用半双工通信
/************************************
使用硬件UART模块和串口中断
************************************/
#include
typedef unsigned int uint;
void configUART(uint baud);
void main() {
EA = 1;
configUART(9600);
while (1) ;
}
void configUART(uint baud) {
SCON = 0x50; //配置串口为模式1,并使能串行接收
TMOD &= 0x0F; //清零T1的控制位
TMOD |= 0x20; //配置T1为模式2(自动重装模式)
TH1 = 256 - 11059200 / 12 / 16 / 2 / baud;
TL1 = TH1;
ET1 = 0; //!!!禁止T1中断(因为做了波特率发生器)
ES = 1; //使能串口中断
TR1 = 1;
}
//中断类型码为4,中断向量的地址 = 中断类型码 * 8 + 3
void interruptUART() interrupt 4 {
if (RI) { //如果接收到了字节
RI = 0; //手动清零
SBUF++; //可以自己设置接收到后数据的处理方式
}
if (TI) { //如果字节发送完毕
TI = 0; //手动清零
}
}
下面的程序把书上的代码做了点优化,加了一个isNewInfo,在主循环里判断只有当接收到了新的字节数据以后才更新显示缓冲区。
#include
typedef unsigned char uchar;
typedef unsigned int uint;
typedef unsigned long ulong;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
uchar code LEDChar[] = { //数码管显示字符转换表
0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E
};
uchar LEDBuf[7] = { //数码管和独立LED的显示缓冲区
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
uchar T0RH = 0; //T0重载值的高字节
uchar T0RL = 0; //T0重载值的低字节
uchar RXDByte = 0; //串口接收到的字节
bit isNewInfo = 0; //是否接收到了新信息
void configTmr0(uint ms);
void configUART(uint baud);
void LEDScan();
//void interruptTmr0();
//void interruptUART();
void main() {
EA = 1; //使能总中断
ENLED = 0; //选择数码管和独立LED
ADDR3 = 1;
configTmr0(1); //配置T0定时1ms
configUART(9600); //配置波特率为9600
while (1) { //将接收字节在数码管上以十六进制形式显示出来
if (isNewInfo) {
LEDBuf[0] = LEDChar[RXDByte & 0x0F];
LEDBuf[1] = LEDChar[RXDByte >> 4];
isNewInfo = 0;
}
}
}
/* 配置并启动T0,ms-T0定时时间 */
void configTmr0(uint ms) {
ulong tmp; //临时变量
tmp = 11059200 / 12; //定时器计数频率
tmp = (tmp * ms) / 1000; //计算所需的计数值
tmp = 65536 - tmp; //计算定时器重载值
tmp = tmp + 13; //补偿中断响应延时造成的误差
T0RH = (uchar)(tmp>>8); //定时器重载值拆分为高低字节
T0RL = (uchar)tmp;
TMOD &= 0xF0; //清零T0的控制位
TMOD |= 0x01; //配置T0为模式1
TH0 = T0RH; //加载T0重载值
TL0 = T0RL;
ET0 = 1; //使能T0中断
TR0 = 1; //启动T0
}
/* 串口配置函数,baud-通信波特率 */
void configUART(uint 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
}
/* LED动态扫描刷新函数,需在定时中断中调用 */
void LEDScan() {
static uchar i = 0; //动态扫描索引
P0 = 0xFF; //关闭所有段选位,显示消隐
P1 = (P1 & 0xF8) | i; //位选索引值赋值到P1口低3位
P0 = LEDBuf[i]; //缓冲区中索引位置的数据送到P0口
if (i < 6) //索引递增循环,遍历整个缓冲区
i++;
else
i = 0;
}
/* T0中断服务函数,完成LED扫描 */
void interruptTmr0() interrupt 1 {
TH0 = T0RH; //重新加载重载值
TL0 = T0RL;
LEDScan(); //LED扫描显示
}
/* UART中断服务函数 */
void interruptUART() interrupt 4 {
if (RI) { //接收到字节
RI = 0; //手动清零接收中断标志位
RXDByte = SBUF; //接收到的数据保存到接收字节变量中
SBUF = RXDByte; //接收到的数据又直接发回,叫作-"echo",
//用以提示用户输入的信息是否已正确接收
isNewInfo = 1;
}
if (TI) { //字节发送完毕
TI = 0; //手动清零发送中断标志位
}
}
上一篇:51单片机 1602液晶显示静态字符
下一篇:51单片机 漩涡流水点阵
推荐阅读最新更新时间:2024-03-16 15:45