笔记:(五)UART串口驱动
Author:家有仙妻谢掌柜
Date:2021/2/26
本文已于2021/3/1更新完毕。
本文用到的数据手册连接在这里
通过理解前面几篇文章的解析,到这里就可以独立理解了,参考数据手册,可以Ctrl+F搜索我这里使用的寄存器,然后就可以理解为什么要这么配置。
这里使用的波特率为9600,可以配置成多种波特率,但是像115200这种就不行,因为误差很大,计算误差的公式也在数据手册上,比较好理解。
有什么疑问可以评论区说出,或者私信,我会尽快回复。感谢支持!
#include "uart.h"
/*串口通信
*只此一组UART
*PA5->RX PA4->TX
*/
#include "include.h"
/*******************************************************************************
* fuction uart_init
* brief 串口初始化函数
* param 无
* return 无
*******************************************************************************/
void uartInit()
{
UartPinConfig(); //UART引脚的配置
UartBuadRateConfig(); //UART波特率的配置
UartInterruptConfig(); //UART中断相关的配置
}
/*******************************************************************************
* fuction sendSingleByte
* brief 串口发送一个字节函数
* param SingleByte:单字节数据
* return 无
*******************************************************************************/
char readUsrReg =0;
void uartsendOneByte(char SingleByte)
{
readUsrReg=_usr;
_txr_rxr = SingleByte;
while(!_tidle);//等待发送完成 0:数据传输中 1:无数据传输
}
/*******************************************************************************
* fuction uartSendBuff
* brief 串口发送多个字节函数
* param uartData:多字节数据 length:数据长度
* return 无
*******************************************************************************/
void uartSendBuff(char *uartData, char length)
{
unsigned char i;
for(i=0; i<length; i++)
{
uartsendOneByte(uartData[i]);
}
}
/*******************************************************************************
* fuction UartRxISR
* brief 串口中断服务子程序
* param UartRxISR:函数名 uartVector:中断向量
* return 无
*******************************************************************************/
char data_buff[3] = {0};
DEFINE_ISR(UartRxISR,uartVector)
{
int i = 0;
int buff_length;
if(_perr || _nf || _ferr || _oerr)//异常情况
{
readUsrReg = _usr;
readUsrReg = _txr_rxr;
RxBuffSizeCnt = 0;
}
else
{
if(_rxif)//接收寄存器状态标志位 0:TXR_RXR寄存器为空 1:TXR_RXR寄存器含有有效数据
{
UartRxBuff[RxBuffSizeCnt] = _txr_rxr;
RxBuffSizeCnt++;
/*******************************************************************/
//根据实际需要自由发挥
//我这里做了限制,因为我要求的通信协议只有两个命令,并且每个命令长度只有三个字节
//我这里是上位机发送53 31/32 50,MCU会回复给上位机通用的数据。
//在/********/之间的程序你随便修改
if(RxBuffSizeCnt==3)
{
if((UartRxBuff[0]==0x53)&&(UartRxBuff[2]==0x50))
{
//收到命令后,要执行的事件标志位置1
EventFlag = 1;
if(UartRxBuff[1]==0x31)//通过串口给MCU发送S:1:P
{
for(i=0;i<RxBuffSizeCnt;i++)
{
data_buff[i] = UartRxBuff[i];
}
uartSendBuff(data_buff,sizeof(data_buff));//同时发送接收到的命令
RxBuffSizeCnt = 0;
memset(UartRxBuff,0,sizeof(UartRxBuff));
}
else if(UartRxBuff[1]==0x32)//通过串口给MCU发送S:2:P
{
//收到命令后,要执行的事件标志位置0
EventFlag = 0;
for(i=0;i<RxBuffSizeCnt;i++)
{
data_buff[i] = UartRxBuff[i];
}
uartSendBuff(data_buff,sizeof(data_buff));//同时发送接收到的命令
RxBuffSizeCnt = 0;
memset(UartRxBuff,0,sizeof(UartRxBuff));
}
}
}
/*******************************************************************/
}
}
}
Rx的信号是中断接收的,于是我直接讲接收处理数据写在了中断函数里,
至于中断为什么这样写,可以参考这篇文章比较详细。
#ifndef _UART_H
#define _UART_H
#include "BH66F2652.h"
#define uartVector 0x28
#define uartTXMaxLength 16
#define uartRXMaxLength 16
volatile unsigned char RxBuffSizeCnt = 0;
volatile unsigned char UartTxBuff[uartTXMaxLength];
volatile unsigned char UartRxBuff[uartRXMaxLength];
#define UartEnableConfig() {_uarten = 1;_rxen = 1;_txen = 1;}
#define UartDisableConfig() {_uarten = 0;_rxen = 0;_txen = 0;}
#define UartPinConfig() {_papu4=0; _papu5=0; _pas13=0; _pas12=1; _pas11=1; _pas10=0;}
#define UartBuadRateConfig() {_bno=0; _prt=0; _stops=0; _brgh=0; _brg=0x0c;} //9600
#define UartInterruptConfig() {_ucr1 = 0x00;_adden = 0; _rie = 1;_tiie = 1;_teie = 1; _uarten = 1;_rxen = 1;_txen = 1;_urf = 0;_txif = 0; _ure = 1; _emi = 1; _ure = 1;}
extern void uartInit();
extern void uartsendOneByte(char SingleByte);
extern void uartSendBuff(char *uartData, char length);
#endif
/*--------------------------------END THE FILE-----------------------------------*/
//至于,你要是想发送什么数据出去,可以这样写
/*******************************************************************************
* fuction SendMeasureData
* brief
* param 无
* return 无
*******************************************************************************/
unsigned char MeasureBuffData[7]={
0x53, //S,按需求修改
0, //
0, //
0, //
0, //
0, //
0x50}; //P,按需求修改
u8 MinusValue = 0;
void SendMeasureData(void)
{
MeasureBuffData[1] = SendData1;//修改
MeasureBuffData[2] = SendData2;//修改
MeasureBuffData[3] = SendData3;//修改
MeasureBuffData[4] = SendData4;//修改
MeasureBuffData[5] = SendData5;//修改
uartSendBuff(MeasureBuffData,sizeof(MeasureBuffData));
}
然后在需要的位置调用这个函数即可SendMeasureData();