📄 uart.c
字号:
#define UART_GLOBALS
#include "config.h"
static uint8 SerLen,ExtData;
static uint8 LenSend; //已发送的有效数据长度
/*
*********************************************************************************************************
** 函数名称:
** 函数功能:串口0中断服务程序
*********************************************************************************************************
*/
void __irq UART0_Isr(void)
{
uint8 IIR;
uint8 temp;
while(((IIR = U0IIR) & 0x01) == 0x00)
{
switch(IIR&0x0e)
{
//=======================================================================================================
case 0x06: // 线状态
temp = U0LSR; // 读出线状态
break;
//=======================================================================================================
case 0x04: // 接收中断
case 0x0C: // 超时中断
{
temp = U0RBR; // 读取数据
if(temp == STX)
{ //在任何时候收到STX,即可视为一帧的开始
RcvStatus = RCVDATA;
SerLen = 0;
RcvDTLen = 0;
SerTmOut = 2; //启动超时定时器
}
else if(temp == ETX)
{
if(RcvStatus == RCVDATA)
{
if(SerTmOut)
{ //在未超时的情况下,接收数据后又收到一个ETX,则本帧数据有效
SerDTValid = TRUE;
}
RcvStatus = RCVSTX;
}
}
//=======================================================================================
else if(RcvStatus == RCVDATA)
{
if((SerTmOut==0) || (temp&0x80))
RcvStatus = RCVSTX; //超时或数据中的bit7为1,则本帧数据作废
else
{
SerTmOut = 2;
if((SerLen&0x07) == 0)
{
//扩展字节
ExtData = temp;
}
else
{
if(ExtData & 0x01)
{
temp |= 0x80;
}
SerBfr[RcvDTLen++] = temp;
ExtData >>= 1;
}
SerLen++;
}
}
//=======================================================================================
if(SerDTValid)
{
SerDTValid = FALSE;
if(RcvDTLen == (SerBfr[LENGTH]+6))
{
temp = 0;
for(SerLen=0;SerLen<RcvDTLen;SerLen++)
temp ^= SerBfr[SerLen];
if(temp == 0xff)
{
if(SerBfr[RADDR] == MyAddr)
{
SerDTValid = TRUE;
}
}
}
}
break;
}
//=======================================================================================================
case 0x02: // 发送中断
{
if(SendStatus == SENDSTX)
{
U0THR = STX;
SendStatus = SENDDATA; //下次中断发送数据
SerLen = 0;
LenSend = 0;
}
else if(SendStatus == SENDDATA)
{
if((SerLen&0x07) == 0)
{
ExtData = 0;
temp = LentoSend>=7?7:LentoSend; //计算扩展数据位长度
do
{
ExtData <<= 1;
if(SerBfr[LenSend+(temp-1)]&0x80)
ExtData |=0x01;
temp--;
}while(temp);
U0THR = ExtData; //发送扩展数据
}
else
{
U0THR = SerBfr[LenSend]&0x7f;
LenSend++;
LentoSend--;
if(LentoSend == 0)
{ //有效数据已发送完毕
SendStatus = SENDETX; //下次中断发送ETX
}
}
SerLen++;
}
else if(SendStatus == SENDETX)
{
U0THR = ETX; //发送ETX
SendStatus = SENDSTOP; //下次中断结束本次发送
}
else if(SendStatus == SENDSTOP)
{
SendFlag = FALSE;
SendStatus = SENDIDLE; //发送器空闲
}
break;
}
//=======================================================================================================
default:
break;
}
}
VICVectAddr = 0x00; // 向量中断结束
}
/*
*********************************************************************************************************
** 函数名称:UART0_Init()
** 函数功能:串口0初始化:baud 8 1 N。
*********************************************************************************************************
*/
void UART0_Init(void)
{
uint16 bak;
PINSEL0 = (PINSEL0 & (~0x0F)) | 0x05; // 管脚连接UART0
VICVectCntl0 = 0x20|0x06; // 分配UART0中断优先级
VICVectAddr0 = (uint32)UART0_Isr; // 设置中断服务程序地址
VICIntEnable = 1 << 0x06; // 使能UART0中断
MyAddr = 0;
BaudNum = 4;
RcvStatus = RCVSTX;
SerDTValid = FALSE;
SerTmOut = 0;
SendFlag = FALSE;
SendStatus = SENDIDLE;
U0LCR = 0x83; // DLAB=1
bak = (Fpclk/16)/BaudRateTable[BaudNum];
U0DLM = bak/256;
U0DLL = bak%256;
U0LCR = 0x03;
U0IER = 0x07; // 允许发送和接收中断
}
/*
*********************************************************************************************************
** 函数名称 :UART0_SendByte()
** 函数功能 :向串口发送字节数据。
** 入口参数 :dat 要发送的数据
** 出口参数 :无
*********************************************************************************************************
*/
void UART0_SendByte (uint8 dat)
{
while((U0LSR & 0x20) == 0); // 等待发送保持寄存器空
U0THR = dat; // 发送一字节数据
}
/*
*********************************************************************************************************
** 函数名称:Ser_Send(0
** 函数功能:发送从机地址,计算校验和(从RAddr开始至应用层信息Info的最后一字节相异或后取反)
*********************************************************************************************************
*/
uint8 Ser_Send(uint8 SlvAddr)
{
uint8 i;
if(SendStatus == SENDIDLE)
{
SerBfr[RADDR] = SlvAddr; //从机地址
SerBfr[SADDR] = MyAddr;
LentoSend = SerBfr[LENGTH]+5;
SerBfr[LentoSend] = 0; // 用于存放校验和
for(i=0;i<LentoSend;i++)
{
SerBfr[LentoSend] ^= SerBfr[i]; // 异或校验
}
SerBfr[LentoSend] = ~SerBfr[LentoSend]; // 取反
LentoSend++;
SerLen = 0;
LenSend = 0;
SendStatus = SENDDATA; // 下次中断发送数据
UART0_SendByte(STX); // 发送数据,产生发送中断
return TRUE;
}
else
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -