1043 字
5 分钟
【通信协议】04 - 串口通信

蓝桥杯部分#

1.串口底层#

#include <Uart.h>
/* 串口初始化函数 */
void UartInit(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xC7; //设置定时初始值
T2H = 0xFE; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES = 1;//允许串口中断
EA = 1;//总中断开启
}
/* 字节发送函数 */
void SendByte(unsigned char dat)
{
SBUF=dat;//将dat数据赋给SBUF,将数据发送出去
while(TI == 0);//等待数据发送
TI = 0;//将发送标志位清零
}
/* 字符串发送函数 */
void Uart_Send_String(unsigned char *dat)
{
while(*dat != '\0')//当字符不为空时,继续发送
SendByte(*dat++);//发送后指针dat加1,指向下一个字节
}

2.单片机发送字符串给上位机#

//头文件引用
#include <Key.h>
#include <Nixie.h>
#include <LED.h>
#include <Init.h>
#include <Uart.h>
#include <INTRINS.H>
unsigned char Nixie_Buf[8]={10,10,10,10,10,10,10,10};//数码管显示数据
unsigned char Nixie_Pos;//数码管数据数组位下标
unsigned char Nixie_Point[8]={0,0,0,0,0,0,0,0};//数码管每一段的“点”数据
unsigned char Key;//键值
unsigned char Key_Up,Key_Down,Key_Val,Key_Old;//按键扫描变量
unsigned char ucLED[8]={0,0,0,0,0,0,0,0};//LED显示数据
unsigned int Nixie_Timer;//数码管定时更新
unsigned int Key_Timer;//按键定时扫描
void Key_Proc(void)//按键检测程序
{
if(Key_Timer) return;//Key_Timer=0时执行下面的语句
Key_Timer=1;
//按键扫描部分//
Key_Val=Key_Read();
Key_Down=Key_Val & (Key_Old ^ Key_Val);
Key_Up=~Key_Val & (Key_Old ^ Key_Val);
Key_Old=Key_Val;
}
void Nixie_Proc(void)//信息处理/显示程序
{
if(Nixie_Timer) return;//Nixie_Timer=0时执行下面的语句
Nixie_Timer=1;
}
void LED_Proc(void)//LED“报警”程序
{
}
void Timer0_Init(void) //1毫秒@12.000MHz
{
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x18; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //定时器中断0打开
EA = 1; //总中断打开
}
void Delay500ms(void) //@12.000MHz
{
unsigned char data i, j, k;
_nop_();
_nop_();
i = 23;
j = 205;
k = 120;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void main()
{
Timer0_Init();//定时器初始化
System_Init();//系统板初始化
Uart1_Init();
Delay500ms();//mark:初始化后若立即发送数据,第一个字节会重复发送,所以先延时500ms,等待UART稳定工作,再发送字符串
Uart1_SendString("Hello UART");//字符串发送数据在开启定时器中断时容易被打断,第一个字节刚好卡在没发完的时刻,造成死循环
while(1)//循环执行任务
{
// Key_Proc();
// Nixie_Proc();
// LED_Proc();
}
}
void Timer0_Server(void) interrupt 1//中断服务程序
{
if(++Nixie_Timer

3.上位机发送字符串给单片机#

PS:按键4可发送单片机接收到的字符串给上位机

串口处理模块#

void Uart1_Server(void) interrupt 4
{
if(RI==1)
{
Uart_RecData[Uart_RecData_Index]=SBUF;
Uart_RecData_Index++;
RI=0;
}
}

按键程序#

void Key_Proc(void)//按键检测程序
{
if(Key_Timer) return;//Key_Timer=0时执行下面的语句
Key_Timer=1;
//按键扫描部分//
Key_Val=Key_Read();
Key_Down=Key_Val & (Key_Old ^ Key_Val);
Key_Up=~Key_Val & (Key_Old ^ Key_Val);
Key_Old=Key_Val;
switch(Key_Down)
{
case 4:
Uart_SendDataFlag=1;
ucLED[0]=1;
break;
}
}

中断程序#

void Uart1_Server(void) interrupt 4
{
if(RI

4.上位机发送数据控制单片机LED#

void Uart_Proc()
{
if(Uart_Timer)return;
Uart_Timer=1;
// if(Uart_RecData[Uart_RecData_Index-1]

2.串口优化#

putchar重定向#

/* 串口初始化函数 */
void UartInit(void) //9600bps@12.000MHz
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x01; //串口1选择定时器2为波特率发生器
AUXR |= 0x04; //定时器时钟1T模式
T2L = 0xC7; //设置定时初始值
T2H = 0xFE; //设置定时初始值
AUXR |= 0x10; //定时器2开始计时
ES = 1;//允许串口中断
EA = 1;//总中断开启
}
extern char putchar(char ch)
{
SBUF=ch; ///将dat数据
while(TI==0);
TI=0;
return(ch);
}
【通信协议】04 - 串口通信
http://www.turinblog.cn/posts/通信协议04---串口通信/
作者
Szturin
发布于
2024-03-23
许可协议
CC BY-NC-SA 4.0