📄 uart.c
字号:
/*************************************************************
WPD800 串口驱动
修改历史 2007-9-25 zaken create version 1.0
*************************************************************/
/*
使用串口0 ,接收采用中断方式
*/
#include "main.h"
#include "string.h"
#include "intctrl.h"
#include "uart.h"
extern volatile DWORD dTCounter;
//波特率表定义
const uint32 brgtlb[]={300,600,1200,2400,4800,9600,19200,38400,115200};
typedef struct tagT_PACKET
{
WORD data_ptr;
WORD data_len;
BYTE data[UART_PACKET_SIZE];
} T_PACKET;
typedef struct tagT_PACKET_LIST
{
WORD l_head;
WORD l_tail;
T_PACKET packet[UART_MAX_PACKET];
} T_PACKET_LIST;
typedef struct tagT_UART_STATUS
{
DWORD RxFrameCnt;//接收桢计数
DWORD RxFrameErrCnt;//接收错误帧计数
DWORD SendFrameCnt;//发送桢计数
}T_UART_STATUS;
typedef struct tagT_UART
{
WORD u_flags;
Uart_Config u_config;
WORD idle_time; /* 接收空闲间隔时间 */
DWORD recv_time; /* 前一个字符的接收时间 */
bool recv_flag; /* UART是否正在接收数据 */
T_PACKET_LIST recv_list; //接收缓冲
T_UART_STATUS status;
}T_UART;
static T_UART tuart;
/* 接收中断回调函数,用以判断数据帧的结束。*/
uint16 huarui94_check_packet(const uint8 *p_data, uint16 data_len)
{
BYTE len;
if(data_len==1)
{
if(p_data[0]!=1)
return UART_PKT_ERR;
}
if(data_len < 5)
return UART_PKT_CON;
len = p_data[2] + 4; //读报文长度
if(data_len >= len)
{
return UART_PKT_FIN;
}
return UART_PKT_CON;
}
//取得串口的配置
int uart_config()
{
return OK;
}
void uart_open(Uart_Config *pcfg)
{
uint32 baudrate,bak;
/* 参数过滤 */
if(pcfg->brg>=UART_BRG_MAX_INDEX)
pcfg->brg=UART_DEFAULT_BRG;
if ((pcfg->databit <5) || (pcfg->databit > 8))
pcfg->databit=8;
if ((pcfg->stopbit == 0) || (pcfg->stopbit > 2))
pcfg->stopbit=0;
if (pcfg->parity > 4)
pcfg->parity=0;
baudrate=brgtlb[pcfg->brg];
/* 设置串口波特率 */
U0LCR = 0x80; // DLAB = 1
bak = (Fpclk >> 4) / baudrate;
U0DLM = bak >> 8;
U0DLL = bak & 0xFF;
/* 设置串口模式 */
bak = pcfg->databit - 5; // 设置字长
if (pcfg->stopbit == 2) bak |= 0x04; // 判断是否为2位停止位
if (pcfg->parity != 0)
{
pcfg->parity =pcfg->parity - 1;
bak |= 0x08;
}
bak |= pcfg->parity << 4; // 设置奇偶校验
U0LCR = bak;
}
static void uart_rx_intr()
{
T_UART *p_uart;
T_PACKET *p_pkt;
WORD callback;
p_uart=&tuart;
p_pkt =&p_uart->recv_list.packet[p_uart->recv_list.l_tail];
if ( !p_uart->recv_flag )
{
p_uart->recv_time =dTCounter;//采样中断计数
p_uart->recv_flag =TRUE;
p_pkt->data_len =0;
}
else
{
if ((DWORD)(dTCounter/*采样中断计数*/-p_uart->recv_time) >= 1000)//超时时间
{
p_pkt->data_len =0;
}
p_uart->recv_time =dTCounter;//采样中断计数
}
p_pkt->data[p_pkt->data_len++] =U0RBR;
/* 如果接收缓冲区满,默认为一帧报文结束 */
if (p_pkt->data_len >= UART_PACKET_SIZE)
{
WORD next =(p_uart->recv_list.l_tail + 1) % UART_MAX_PACKET;
if (next != p_uart->recv_list.l_head)
{
p_uart->recv_list.l_tail =next;
}
p_uart->recv_flag =FALSE;
return;
}
/* call callback function to validate the packet. */
if ( !p_uart->u_config.pcb )
{
return;
}
callback =(*p_uart->u_config.pcb)(p_pkt->data, p_pkt->data_len);
if (callback == UART_PKT_FIN)
{
WORD next =(p_uart->recv_list.l_tail + 1) % UART_MAX_PACKET;
p_uart->status.RxFrameCnt++;
if (next != p_uart->recv_list.l_head)
{
p_uart->recv_list.l_tail =next;
}
else //缓冲满,记录错误状态
RECORD_ERR_FLAG(4);//接收缓冲溢出
p_uart->recv_flag =FALSE;
}
else if (callback == UART_PKT_ERR)
{
p_uart->status.RxFrameErrCnt++;
p_uart->recv_flag =FALSE;
}
}
void __irq uart_interrupt (void)
{
uint8 status;
while(((status=U0IIR)& 0x01)==0)//中断处理
{
switch(status & 0x0e)
{
case 0x02://接收中断,未使能,如果产生报错
//置错误位
RECORD_ERR_FLAG(0);
break;
case 0x04:
uart_rx_intr();
break;
case 0x06://线状态
//置错误位
RECORD_ERR_FLAG(1);
RECORD_ERR_STATUS(U0LSR);//读LSR复位中断
break;
case 0x0c://字符超时
RECORD_ERR_FLAG(2);
RECORD_ERR_STATUS(U0RBR);//读RBR复位中断
break;
default:
RECORD_ERR_FLAG(3);
break;
}
VICVectAddr = 0x00; // 中断处理结束
}
}
//串口初始化
int32 uart_init(void)
{
tuart.u_config.brg=UART_DEFAULT_BRG;
tuart.u_config.databit=8;
tuart.u_config.stopbit=0;
tuart.u_config.parity=0;
tuart.u_config.pcb=huarui94_check_packet;
//清接收发送缓冲未写
PINSEL0 = (PINSEL0 & 0xfffffff0)|0x00000005; // 设置I/O连接到UART0
uart_open(&tuart.u_config); // 串口初始化
U0FCR = 0x01; // 使能FIFO,并设置触发点为1字节
U0IER = 0x05; // 允许RBR中断,即接收中断和rx线状态中断
return Int_Setup(6,(uint32)uart_interrupt,0,0);
/*
IRQEnable(); // 使能IRQ中断
VICIntSelect = 0x00000000; // 设置所有的通道为IRQ中断
VICVectCntl0 = 0x20 | 0x06; // UART0分配到IRQ slot0,即最高优先级
VICVectAddr0 = (uint32)uart_interrupt; // 设置UART0向量地址
VICIntEnable = 1 << 0x06; // 使能UART0中断
*/
//return OK;
}
WORD UART_Read(BYTE *p_data)
{
WORD next, bytes_read;
T_UART *p_uart;
T_PACKET *p_pkt;
p_uart =&tuart;
next =p_uart->recv_list.l_head;
if (next == p_uart->recv_list.l_tail)
{
return 0;
}
p_pkt =&p_uart->recv_list.packet[next];
bytes_read =p_pkt->data_len;
memcpy(p_data, p_pkt->data, bytes_read);
p_uart->recv_list.l_head =(next + 1) % UART_MAX_PACKET;
return bytes_read;
}
WORD UART_Write(const BYTE *p_data, WORD data_len)
{
WORD i;
if ((data_len == 0) || (data_len > UART_PACKET_SIZE))
{
return 0;
}
for(i=0;i<data_len;i++)
{
U0THR = p_data[i]; // 要发送的数据
while ((U0LSR & 0x40) == 0);
}
tuart.status.SendFrameCnt++;
return data_len;
}
void Uart_Close()//关闭串口,切换规约时
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -