📄 uart.c
字号:
/****************************************Copyright (c)**************************************************
**--------------文件信息--------------------------------------------------------------------------------
**描 述: μCOS-II下LPC2114的UART0底层驱动
**--------------当前版本修订------------------------------------------------------------------------------
** 修改人: hongding
** 日 期:
** 描 述:
** 08-11-16 UART1,用于 接收 GPRS AT指令返回 和 服务器桢,如果 g_GPRS_recv 为1,则接收的字符一定是AT指令返回
** 08-12-4 GPRS AT返回指令的接收 初步采取 查询方式接收
** 08-12-31 Uart1_recv 改为长度 50 服务器帧的 最大程度为50
** 09-1-08 增加 U0_Post_flag 和 g_meter_wait ; 485网络原因 连续操作两个不同的表具之间要有延时因此 增加两标识用于
** 对 URAT0的释放进行控制 ; 在 时钟钩子函数中对其进行操作
** 09-3-1 增加 Uart0ScannerInit()函数; g_Uart0_Func标志;
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#define IN_UART0
#include "config.h"
/*中继器运行 所需要的一些变量定义*/
static SendQueue sendQueue;
static RecvQueue recvQueue;
static RecvQueue recvQueue_U1;
static SendQueue sendQueue_U1;
uint8 Uart1_recv[50];
OS_EVENT * Uart0Sem; /* UART0占用 此信号量在 节拍钩子函数 中进行释放 */
OS_EVENT * Uart0recvSem;
static OS_EVENT * Uart1Sem;
OS_EVENT * Uart1_Mbox; /* UATR1邮箱*/
volatile uint8 g_Mbox_Complete ; /* 标识邮箱的信息桢是否完成处理 在frameanalyse任务中被置位*/
static uint16 UART0_OWN_Flag ; /* 可同时使用 UART0 的任务最多16 个*/
volatile uint16 g_meter_wait ;
volatile uint8 U0_Post_flag ; /* 用于控制 UART0 的释放*/
/*数据接收完成?? 前面为什么不能加 volatile*/
//uint8 rbrb,rbrc,rbrd,rbre;//测试
/*扫描仪运行所需变量定义*/
volatile uint8 g_Uart0_Func ; /* 用于标志 Uart0 的用途(连接表具 或 连接扫描仪),从而决定中断函数的执行 */
volatile uint8 g_Eint0_Int ; /* 用于识别有扫描仪输入的请求 */
/*********************************************************************************************************
** 函数名称: UART0Init
** 功能描述: 初始化UART0
** 输 入: bps:波特率
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8 UART0Init(uint32 bps)
{
uint16 Fdiv;
/*UART0 设置*/
U0LCR = 0x80; /* 允许访问分频因子寄存器 */
Fdiv = (Fpclk / 16) / bps; /* 设置波特率 */
U0DLM = Fdiv / 256;
U0DLL = Fdiv % 256;
U0LCR = 0x1b; /* 禁止访问分频因子寄存器 且设置为8,1,n */
U0FCR = 0x87; /* 初始化FIFO */
g_Uart0_Func = 0 ; /* 标示用于485的操作 */
U0IER = U0IER&(~0x07); /*禁止 接收 \发送中断*/
/*UART0 数据资源初始化*/
Uart0Sem = OSSemCreate(1);
Uart0recvSem = OSSemCreate(0);
if ((Uart0Sem != NULL)&&(Uart0recvSem!=NULL))
{
return TRUE;
}
else
{
return FALSE;
}
}
/*********************************************************************************************************
** 函数名称: UART0ScannerInit
** 功能描述: 初始化UART0 扫描仪用途
** 输 入: bps:波特率
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8 UART0ScannerInit(uint32 bps)
{
uint16 Fdiv;
/*UART0 设置 / 可与共用 Uart0recvSem 信号量 */
U0LCR = 0x80; /* 允许访问分频因子寄存器 */
Fdiv = (Fpclk / 16) / bps; /* 设置波特率 */
U0DLM = Fdiv / 256;
U0DLL = Fdiv % 256;
U0LCR = 0x03; /* 禁止访问分频因子寄存器 且设置为8,1,n */
U0FCR = 0x87; /* 初始化FIFO */
g_Uart0_Func = 1 ; /* 标示用于扫描仪的操作*/
U0IER = U0IER&(~0x07); /*禁止 接收 \ 发送中断*/
return 0 ;
}
/*********************************************************************************************************
** 函数名称: UART0_PostFlag
** 功能描述: 功能 对UART0 占用标识UART0_PEND_Flag 释放
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_PostFlag(uint8 Taskprio)
{
OS_ENTER_CRITICAL() ;
UART0_OWN_Flag &= ~ Task_Mask[Taskprio] ;
OS_EXIT_CRITICAL() ;
}
/*********************************************************************************************************
** 函数名称: UART0_PendFlag
** 功能描述: 功能 对UART0 占用标识UART0_PEND_Flag 置位
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_PendFlag(uint8 Taskprio)
{
OS_ENTER_CRITICAL() ;
UART0_OWN_Flag |= Task_Mask[Taskprio] ;
OS_EXIT_CRITICAL() ;
}
/*********************************************************************************************************
** 函数名称: IS_PendFlag
** 功能描述: 功能 对UART0 占用标识UART0_PEND_Flag 判断
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
uint8 IS_PendFlag(uint8 Taskprio)
{
if(UART0_OWN_Flag & Task_Mask[Taskprio]){
return 1 ;
}else{
return 0 ;
}
}
/*********************************************************************************************************
** 函数名称: UART0_SendQ
** 功能描述: 发送一组数据(若用于向扫描仪发送数据 则只需 设置前两个参数 即 DQ_head 和 DataN )
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_SendQ(const void * DQ_head, uint16 DataN, void * RBuff ,uint8 Taskprio)
{
uint8 err;
if(0 == g_Uart0_Func){ // 当用于485用途时 才需竞争Uart0
OSSemPend(Uart0Sem ,0 ,&err);
UART0_PendFlag(Taskprio); /*此处可以看到当前 UART0 正在被哪个任务使用
可用于任务等待超时后的判断*/
IO0SET = R485; /*准备485发送,并挂上发送队列和接收队列*/
OSTimeDly(6);
}
OS_ENTER_CRITICAL();
sendQueue.DQ_head = (QUEUE_DATA_TYPE *)DQ_head; //设置发送队列
sendQueue.pData = (QUEUE_DATA_TYPE *)DQ_head;
sendQueue.DataNum = DataN;
if(0 == g_Uart0_Func){
recvQueue.RBuff = (QUEUE_DATA_TYPE *)RBuff; //当用于485用途时 设置接收队列
recvQueue.pData = recvQueue.RBuff;
recvQueue.DataNum = 0;
recvQueue.start = 0;
}
OS_EXIT_CRITICAL();
U0THR = 0xFE;
U0THR = 0xFE; /*启动THR中断 需前导字节初始化 FIFO*/
U0IER = U0IER | 0x02; /*使能发送中断*/
}
/*********************************************************************************************************
** 函数名称: UART0_RecvReset
** 功能描述: 等待超时时 重置UART0
** 输 入:
** 输 出:
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_RecvReset(uint8 TaskPrio)
{
OS_ENTER_CRITICAL();
OSSemPost(Uart0Sem);
UART0_PostFlag(TaskPrio);
recvQueue.RBuff = NULL; //重置接收缓存控制结构
recvQueue.pData = NULL;
recvQueue.DataNum = 0;
recvQueue.start = 0;
U0IER &=(~0x01); //关接收中断
IO0SET = R485;
OS_EXIT_CRITICAL();
}
/*********************************************************************************************************
** 函数名称: UART0_ScanRecvSet()
** 功能描述: 发送一组数据
** 输 入: 无
** 输 出: 接收到的数据
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_ScanRecvSet(void * RBuff)
{
OS_ENTER_CRITICAL();
recvQueue.RBuff = (QUEUE_DATA_TYPE *)RBuff; //当用于485用途时 设置接收队列
recvQueue.pData = recvQueue.RBuff;
recvQueue.DataNum = 0;
recvQueue.start = 0;
U0IER |= 0x01; //启动接收中断
OS_EXIT_CRITICAL();
}
/*********************************************************************************************************
** 函数名称: UART0_Exception
** 功能描述: UART0中断服务程序
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void UART0_Exception(void)
{
uint8 IIR, temp , i;
uint16 dataNum = 0;
uint16 dataLen ; // 用于计算扫描仪配置桢的数据长度
OS_ENTER_CRITICAL();
IIR = U0IIR;
/* 有中断未处理完 */
switch (IIR & 0x0e)
{
case 0x02:
dataNum=sendQueue.DataNum;
if(sendQueue.DQ_head == NULL){
U0IER = U0IER&(~0x02); /* THRE中断 */
}else{
if(!dataNum){ /*数据发送完 准备接收数据*/
Delay(2);
sendQueue.DQ_head = NULL;
sendQueue.pData = NULL;
U0IER &=(~0x02);
IO0CLR = R485; /* 清零485准备接收 表具返回桢*/
U0IER |= 0x01; /* 发送OVER 启动RBR中断 准备接收数据*/
}
for(i=16;i!=0;i--) /*如果发送允许(U0THR为空)*/
{
U0THR = *sendQueue.pData++;
if(0==--dataNum) break;
}
if(!dataNum){
sendQueue.DataNum = dataNum;
break; /*此时数据还未彻底发送出去(只是把它放在了缓存里),
等到下一次发送中断(发送缓存为空),才证明都以发送成功 */
}else{
sendQueue.DataNum = dataNum;
}
}
break;
case 0x04: /* 接收数据可用 */
if(recvQueue.RBuff != NULL){
dataNum = recvQueue.DataNum;
for(i=8;i!=0;i--){
temp = U0RBR;
if(temp == 0x68){
recvQueue.start = 1;
}
if(recvQueue.start==1){
*recvQueue.pData++ = temp;
dataNum++;
}
if((0 == g_Uart0_Func)&&(0x16==temp)&&(*(recvQueue.RBuff+2)==(uint8)(dataNum-5))){
OSSemPost(Uart0recvSem); /*通知任务拿数据*/
/*释放UART0 一次帧发送和帧返回作为一次串口占用 如果 表具无响应的话
那么 Uart0recvSem和 Uart0Sem 就得不到释放 所以等待超时后 先释放信号量 */
UART0_OWN_Flag = 0 ;
U0_Post_flag = 1 ;
g_meter_wait = MANI_METER_WAIT ; /*连续操作485网络 需间隔延时 在时钟钩子函数中对其进行释放*/
recvQueue.RBuff = NULL; //重置接收缓存控制结构
recvQueue.pData = NULL;
recvQueue.DataNum = 0;
recvQueue.start = 0;
U0IER &=(~0x01);
//IO0SET = R485;
break;
}
if((1 == g_Uart0_Func)&&(0x16==temp)){ //用于扫描仪接收时的判断
dataLen = *(recvQueue.RBuff+5)*100 + *(recvQueue.RBuff+6) ;
if(dataLen == (dataNum-9)){
OSSemPost(Uart0recvSem); /*通知任务拿数据*/
/*UART0_OWN_Flag = 0 ;
U0_Post_flag = 1 ;
g_meter_wait = MANI_METER_WAIT ; 用于扫描仪时不需要*/
recvQueue.RBuff = NULL; //重置接收缓存控制结构
recvQueue.pData = NULL;
recvQueue.DataNum = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -