前言 串口是最常用的通讯方式,简单方便,所以我们先实现该接口。我们需要实现一个比较好用的串口驱动,方便后面各种基于串口的模块使用。老规矩我们还是从手册开始一点一点进行驱动的实现。 过程串口模块介绍IO引脚UART0 P410 P411 UART4 P205 P206 UART9 P109 P110 参考手册《27. Serial Communica tions Interface (SCI) 》 瑞萨的SCI与其他家有点不一样,瑞萨家的SCI是一个大集合,包括了UART,SPI,IIC等串行通讯接口,按照不同配置可以实现不同的接口。我们这里只关注UART。 首先我们要从以下方向了解SCI模块 整体框图如下 时钟SCI使用PLCKA 需要先使能外设时钟 MSTPCRB的bit31 27 22分别对应SCI0 SCI4 SCI9,默认为1不使能,需要修改为0使能。 寄存器l RSR:移位寄存器,收到数据后自动放入RDR, RDRHL或者接收FIFO,CPU也可以直接访问(虽然一半不会这么做)。 l RDR:只读接收数据寄存器,RSR接收到一字节后复制到RDR,然后RSR可以继续接收。RDR必须有接收标志SCIn_RXI才能去读,如果没来得及读出RSR又有新的数据过来会溢出。 l RDRHL:类似于RDR只是是Non-Manchester模式9位串口模式使用,16位,低8位就是RDR的影子寄存器。7位9位模式不能访问。 l RDRHL_MAN:类似于RDRHL只是是Manchester模式使用,有一些其他同步信息。 l FRDRHL/FRDRH/FRDRL: FIFO模式下读数据和状态,读出的状态和SSR_FIFO一样,写SSR_FIFO 寄存器的对应bit为0清除状态(注意只需要清除的标志位写0其他位写1)。最好一起直接16位读FRDRHL,硬是要分开8位读,则先读FRDRH再读FRDRL。 l TDR:发送寄存器,发送移位寄存器TSR空时,自动TDR移动到TSR进行发送。可读可写,只有发送空SCIn_TXI(TDR已经移动到TSR)才能进行下一次写。 l TDRHL:类似于TDR, Non-Manchester模式使用。 l TDRHL_MAN:类似于TDRHL Manchester模式使用,有一些其他同步信息。 l FTDRHL/FTDRH/FTDRL:类似于TDR,不过是FIFO模式使用。 l TSR:发送移位寄存器。TDR数据自动移动到TSR再按位发出,CPU不能直接访问。 l SMR: Non-Smart Card模式的串行模式选择,即选择串口的额时钟源,是否多机模式,停止校验,数据长度,模式是SPI,IIC还是UART。 l SMR_SMCI:Smart Card接口使用我们这里不关心。 l SCR: Non-Smart Card模式串行接口控制,收发使能控制,收发多机处理中断使能控制,时钟输出控制 l Non-Smart Card:Smart Card接口使用我们这里不关心。 l SSR状态寄存器: Non-Smart Card , Non-FIFO 模式使用。 l SSR_FIFO:状态寄存器FIFO模式,Non-Smart Card模式使用。 l SSR_SMCI:Smart Card接口使用我们这里不关心。 l SSR_MANC:Manchester模式使用我们这里不关心。 l SCMR:Smart Card模式使用我们这里不关心。 l BRR:波特率设置寄存器 l MDDR:波特率微调寄存器(调整小数部分) l SEMR:调制参数配置,这里不使用不关心。 l SNFR:噪声过滤,串口模式只能设置为0 l SIMR1,SIMR2,SIMR3,SISR:IIC相关这里不关心 l SPMR:SPI相关这里不关心 l FCR:FIFO控制 l FDR:FIFO中收发数据个数。 l LSR:错误计数,溢出标志 l CDR,DCCR:多机通讯有地址匹配的才使用,这里不关心. l SPTRL:端口配置电平翻转等。 l ACTR:时序调整配置 l MMR,TMPR,RMPR,MESR,MECR:Manchester模式使用这里不关心。 l ESMER:Extended Serial Module控制这里不使用不关心。 l CR0,CR1,CR2,CR3 l PCR:端口极性控制。 l ICR:中断控制 l STR:状态 l STCR:状态清除 l CF0DR,CF0CR,CF0RR,PCF1DR,SCF1DR,CF1CR,CF1RR,不使用不关心 l TCR,TMR,TPRE,TCNT不使用不关心。 信号采样串口是以16倍bit速率采样的,也就是一个bit的时间有16个CLK,在第8个CLK进行采样,也就是中间位置读输入引脚状态。 波特率计算 配置流程引脚配置-> 使能时钟-> 参数配置-> 串口中断配置-> NVIC中断配置-> 使能 串口驱动实现有driver和hal层实现,driver层只需要调用hal层的接口即可。 整体思想如下: 对于接收,串口接收中断将数据写入缓冲区,串口接收接口查询缓冲区读出即可,无数据则等待或者返回错误 对于发送,发送接口将数据写入缓冲区,串口发送中断中查询缓冲区有则继续发送,直到发送完,所以第一次如果未处于发送中则需要手动触发一次中断,后续就都是在发送完中断中处理。 核心代码 hal_uart.c
- #include "R7FA4M2AD.h"
- #include "hal_uart.h"
- #include "clk.h"
- // read FRDRHL SSR_FIFO FDR
- /**
- *****************************************************************************
- * fn int HAL_UART_Init(HAL_UART_ID_e id)
- * brief 初始化UART模块,完成模块相关必要的初始化配置.
- * note 使用UART前必须调用,所有UART按默认配置(BSP实现).
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * retval 0 初始化成功.
- * retval -1 初始化失败.
- *****************************************************************************
- */
- int HAL_UART_Init(HAL_UART_ID_e id)
- {
- return 0;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_CheckSend(HAL_UART_ID_e id,unsigned char byte)
- * brief 查询的方式发送一个字节.
- * note 阻塞发送,直到发送完才会返回.
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] byte 需要发送的字节.
- * retval 0 发送成功.
- * retval 其他值 发送失败(实际上没有发送完会阻塞所以不会返回其他值).
- *****************************************************************************
- */
- int HAL_UART_CheckSend(HAL_UART_ID_e id,unsigned char value)
- {
- int res = 0;
- switch(id)
- {
- case 0:
- if(R_SCI0->SSR_FIFO_b.TDFE == 1)
- {
- R_SCI0->FTDRL = value;
- res = 0;
- }
- else
- {
- res = -1;
- }
- break;
- case HAL_UART_4:
- if(R_SCI4->SSR_FIFO_b.TDFE == 1)
- {
- R_SCI4->FTDRL = value;
- res = 0;
- }
- else
- {
- res = -1;
- }
- break;
- case HAL_UART_9:
- if(R_SCI9->SSR_FIFO_b.TDFE == 1)
- {
- R_SCI9->FTDRL = value;
- res = 0;
- }
- else
- {
- res = -1;
- }
- break;
- default:
- res = -1;
- break;
- }
- return res;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_CheckRead(HAL_UART_ID_e id,unsigned char* byte);
- * brief 查询的方式读一个字节.
- * note 阻塞读,直到有数据才会返回.
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] byte 存储读到的字节.
- * retval 0 读成功.
- * retval 其他值 读失败(实际上读不到数据会阻塞所以不会返回其他值).
- *****************************************************************************
- */
- int HAL_UART_CheckRead(HAL_UART_ID_e id,unsigned char* byte)
- {
- return 0;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_Send(HAL_UART_ID_e id,unsigned char byte)
- * brief 直接发送一个字节.
- * note 直接发送,直接往硬件发送缓冲写字节立即返回.
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] byte 需要发送的字节.
- * retval 0 发送成功.
- * retval 其他值 发送失败(实际上不会返回其他值).
- *****************************************************************************
- */
- int HAL_UART_Send(HAL_UART_ID_e id,unsigned char byte)
- {
- return 0;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_Read(HAL_UART_ID_e id,unsigned char* byte);
- * brief 直接读一个字节.
- * note 直接读,直接读硬件缓冲立即返回.
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] byte 存储读到的字节.
- * retval 0 读成功.
- * retval 其他值 读失败(实际上不会返回其他值).
- *****************************************************************************
- */
- int HAL_UART_Read(HAL_UART_ID_e id,unsigned char* byte)
- {
- return 0;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_SetTxISRCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- * brief 设置发送缓冲区空中断服务回调函数.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] callbackfun 回调函数.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_SetTxISRCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- {
- return 0;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_SetTxCmpISRCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- * brief 设置发送完中断服务回调函数.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] callbackfun 回调函数.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_SetTxCmpISRCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- {
- return 0;;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_SetRxCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- * brief 设置接收缓冲满中断服务回调函数.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] callbackfun 回调函数.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_SetRxCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- {
- return 0;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_SetRxErrCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- * brief 设置接收错误中断服务回调函数.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] callbackfun 回调函数.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_SetRxErrCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- {
- return 0;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_SetCfg(HAL_UART_ID_e id,HAL_UART_CFG_t* cfg)
- * brief 配置UART参数.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] cfg 指向配置参数结构体 ref HAL_UART_CFG_t.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_SetCfg(HAL_UART_ID_e id,HAL_UART_CFG_t* cfg)
- {
- int res = 0;
- switch(id)
- {
- case HAL_UART_0:
- /* Enable CLK */
- R_MSTP->MSTPCRB_b.MSTPB31 = 0; /* SCI0 */
-
- /* disable */
- R_SCI0->SCR_b.RE = 0;
- R_SCI0->SCR_b.TE = 0;
-
- /*P410 RXD0 PSEL:4
- *P411 TXD0 PSEL:4
- */
- R_PMISC->PWPR_b.B0WI = 0;
- R_PMISC->PWPR_b.PFSWE = 1;
-
- R_PFS->PORT[4].PIN[10].PmnPFS_b.PODR = 1; /*0: Low output 1: High output */
- //R_PFS->PORT[4].PIN[10].PmnPFS_b.PIDR /*0: Low level 1: High level */
- R_PFS->PORT[4].PIN[10].PmnPFS_b.PDR = 0; /*0: Input (functions as an input pin) 1: Output (functions as an output pin) */
- R_PFS->PORT[4].PIN[10].PmnPFS_b.PCR = 1; /*0: Disable input pull-up 1: Enable input pull-up */
- //R_PFS->PORT[4].PIN[10].PmnPFS_b.PIM /* This bit is read as 0. The write value should be 0. */
- R_PFS->PORT[4].PIN[10].PmnPFS_b.NCODR = 0; /* 0: CMOS output 1: NMOS open-drain output */
- R_PFS->PORT[4].PIN[10].PmnPFS_b.DSCR = 3; /* 00: Low drive 01: Middle drive 10: Setting prohibited 11: High drive */
- R_PFS->PORT[4].PIN[10].PmnPFS_b.EOFR = 0; /* 00: Don't care 01: Detect rising edge 01: Detect rising edge 11: Detect both edges*/
- R_PFS->PORT[4].PIN[10].PmnPFS_b.ISEL = 0; /* 0: Not used as an IRQn input pin 1: Used as an IRQn input pin */
- R_PFS->PORT[4].PIN[10].PmnPFS_b.ASEL = 0; /* 0: Not used as an analog pin 1: Used as an analog pin */
- R_PFS->PORT[4].PIN[10].PmnPFS_b.PMR = 1; /* 0: Used as a general I/O pin 1: Used as an I/O port for peripheral functions */
- R_PFS->PORT[4].PIN[10].PmnPFS_b.PSEL = 4; /* Peripheral Select */
-
- R_PFS->PORT[4].PIN[11].PmnPFS_b.PODR = 1; /*0: Low output 1: High output */
- //R_PFS->PORT[4].PIN[11].PmnPFS_b.PIDR /*0: Low level 1: High level */
- R_PFS->PORT[4].PIN[11].PmnPFS_b.PDR = 1; /*0: Input (functions as an input pin) 1: Output (functions as an output pin) */
- R_PFS->PORT[4].PIN[11].PmnPFS_b.PCR = 1; /*0: Disable input pull-up 1: Enable input pull-up */
- //R_PFS->PORT[4].PIN[11].PmnPFS_b.PIM /* This bit is read as 0. The write value should be 0. */
- R_PFS->PORT[4].PIN[11].PmnPFS_b.NCODR = 0; /* 0: CMOS output 1: NMOS open-drain output */
- R_PFS->PORT[4].PIN[11].PmnPFS_b.DSCR = 3; /* 00: Low drive 01: Middle drive 10: Setting prohibited 11: High drive */
- R_PFS->PORT[4].PIN[11].PmnPFS_b.EOFR = 0; /* 00: Don't care 01: Detect rising edge 01: Detect rising edge 11: Detect both edges*/
- R_PFS->PORT[4].PIN[11].PmnPFS_b.ISEL = 0; /* 0: Not used as an IRQn input pin 1: Used as an IRQn input pin */
- R_PFS->PORT[4].PIN[11].PmnPFS_b.ASEL = 0; /* 0: Not used as an analog pin 1: Used as an analog pin */
- R_PFS->PORT[4].PIN[11].PmnPFS_b.PMR = 1; /* 0: Used as a general I/O pin 1: Used as an I/O port for peripheral functions */
- R_PFS->PORT[4].PIN[11].PmnPFS_b.PSEL = 4; /* Peripheral Select */
-
- R_PMISC->PWPR_b.PFSWE = 0;
- R_PMISC->PWPR_b.B0WI = 1;
-
- /*
- * set param
- */
- R_SCI0->SMR_b.CKS = 0; /* 00: PCLK clock (n = 0) 01: PCLK/4 clock 10: PCLK/16 clock 11: PCLK/64 clock */
- R_SCI0->SMR_b.MP = 0; /*0: Disable multi-processor communications function 1: Enable multi-processor communications function */
- R_SCI0->SMR_b.STOP = 0; /*0: 1 stop bit 1: 2 stop bits */
- R_SCI0->SMR_b.PM = 0; /* 0: Even parity 1: Odd parity */
- R_SCI0->SMR_b.PE = 0; /* 0: Parity Disable 1: Parity Enable */
- R_SCI0->SMR_b.CHR = 0; /* SCMR.CHR1=0: 0-9bits 1-9bits SCMR.CHR1=1: 0-8bits 1-7bits */
- R_SCI0->SMR_b.CM = 0; /* 0: Asynchronous mode or simple IIC mode 1: Clock synchronous mode or simple SPI mode*/
-
- R_SCI0->SCR_b.CKE = 0; /*1 Clock Enable 0 Clock Disable*/
- R_SCI0->SCR_b.TEIE = 0; /* 0: Disable SCIn_TEI interrupt requests 1: Enable SCIn_TEI interrupt requests */
- R_SCI0->SCR_b.MPIE = 0;
- R_SCI0->SCR_b.RIE = 1;
- R_SCI0->SCR_b.TIE = 0;
-
- R_SCI0->FCR_b.FM = 1; /* 0: Non-FIFO mode. 1: FIFO mode. */
- R_SCI0->FCR_b.RFRST = 1; /* 0: Do not reset FRDRHL 1: Reset FRDRHL */
- R_SCI0->FCR_b.RFRST = 0;
- R_SCI0->FCR_b.TFRST = 1; /* 0: Do not reset FTDRHL 1: Reset FTDRHL */
- R_SCI0->FCR_b.TFRST = 0;
- R_SCI0->FCR_b.DRES = 0; /*Receive Data Ready Error Select Selects the interrupt requested when detecting receive data ready. 0: Receive data full interrupt (SCIn_RXI) 1: Receive error interrupt (SCIn_ERI) */
- R_SCI0->FCR_b.TTRG = 1; /* Transmit FIFO Data Trigger Number */
- R_SCI0->FCR_b.RTRG = 1; /* Receive FIFO Data Trigger Number */
- R_SCI0->FCR_b.RSTRG = 0; /* RTS Output Active Trigger Number Select */
-
- R_SCI0->SEMR_b.BRME = 1;
- R_SCI0->SEMR_b.ABCS = 0;
- R_SCI0->SEMR_b.BGDM = 0;
- R_SCI0->SEMR_b.ABCSE = 0;
- /*
- * set baud
- * PCLK/(64*2^(2*n-1))*(256/M)*B - 1 n=0 CKS[1:0]=0
- */
- R_SCI0->BRR = clk_get_pclka()/(32*cfg->baud) - 1;
- R_SCI0->MDDR = 256;
- /*
- * enable
- */
- R_SCI0->SCR_b.RE = 1;
- R_SCI0->SCR_b.TE = 1;
- break;
- case HAL_UART_4:
- /* Enable CLK */
- R_MSTP->MSTPCRB_b.MSTPB27 = 0; /* SCI4 */
-
- /*P205 TXD4 PSEL:4
- *P206 RXD4 PSEL:4
- */
- R_PMISC->PWPR_b.B0WI = 0;
- R_PMISC->PWPR_b.PFSWE = 1;
-
- R_PFS->PORT[2].PIN[6].PmnPFS_b.PODR = 1; /*0: Low output 1: High output */
- //R_PFS->PORT[2].PIN[6].PmnPFS_b.PIDR /*0: Low level 1: High level */
- R_PFS->PORT[2].PIN[6].PmnPFS_b.PDR = 0; /*0: Input (functions as an input pin) 1: Output (functions as an output pin) */
- R_PFS->PORT[2].PIN[6].PmnPFS_b.PCR = 1; /*0: Disable input pull-up 1: Enable input pull-up */
- //R_PFS->PORT[2].PIN[6].PmnPFS_b.PIM /* This bit is read as 0. The write value should be 0. */
- R_PFS->PORT[2].PIN[6].PmnPFS_b.NCODR = 0; /* 0: CMOS output 1: NMOS open-drain output */
- R_PFS->PORT[2].PIN[6].PmnPFS_b.DSCR = 3; /* 00: Low drive 01: Middle drive 10: Setting prohibited 11: High drive */
- R_PFS->PORT[2].PIN[6].PmnPFS_b.EOFR = 0; /* 00: Don't care 01: Detect rising edge 01: Detect rising edge 11: Detect both edges*/
- R_PFS->PORT[2].PIN[6].PmnPFS_b.ISEL = 0; /* 0: Not used as an IRQn input pin 1: Used as an IRQn input pin */
- R_PFS->PORT[2].PIN[6].PmnPFS_b.ASEL = 0; /* 0: Not used as an analog pin 1: Used as an analog pin */
- R_PFS->PORT[2].PIN[6].PmnPFS_b.PMR = 1; /* 0: Used as a general I/O pin 1: Used as an I/O port for peripheral functions */
- R_PFS->PORT[2].PIN[6].PmnPFS_b.PSEL = 4; /* Peripheral Select */
-
- R_PFS->PORT[2].PIN[5].PmnPFS_b.PODR = 1; /*0: Low output 1: High output */
- //R_PFS->PORT[2].PIN[5].PmnPFS_b.PIDR /*0: Low level 1: High level */
- R_PFS->PORT[2].PIN[5].PmnPFS_b.PDR = 1; /*0: Input (functions as an input pin) 1: Output (functions as an output pin) */
- R_PFS->PORT[2].PIN[5].PmnPFS_b.PCR = 1; /*0: Disable input pull-up 1: Enable input pull-up */
- //R_PFS->PORT[2].PIN[5].PmnPFS_b.PIM /* This bit is read as 0. The write value should be 0. */
- R_PFS->PORT[2].PIN[5].PmnPFS_b.NCODR = 0; /* 0: CMOS output 1: NMOS open-drain output */
- R_PFS->PORT[2].PIN[5].PmnPFS_b.DSCR = 3; /* 00: Low drive 01: Middle drive 10: Setting prohibited 11: High drive */
- R_PFS->PORT[2].PIN[5].PmnPFS_b.EOFR = 0; /* 00: Don't care 01: Detect rising edge 01: Detect rising edge 11: Detect both edges*/
- R_PFS->PORT[2].PIN[5].PmnPFS_b.ISEL = 0; /* 0: Not used as an IRQn input pin 1: Used as an IRQn input pin */
- R_PFS->PORT[2].PIN[5].PmnPFS_b.ASEL = 0; /* 0: Not used as an analog pin 1: Used as an analog pin */
- R_PFS->PORT[2].PIN[5].PmnPFS_b.PMR = 1; /* 0: Used as a general I/O pin 1: Used as an I/O port for peripheral functions */
- R_PFS->PORT[2].PIN[5].PmnPFS_b.PSEL = 4; /* Peripheral Select */
-
- R_PMISC->PWPR_b.PFSWE = 0;
- R_PMISC->PWPR_b.B0WI = 1;
-
- /*
- * set param
- */
- R_SCI4->SMR_b.CKS = 0; /* 00: PCLK clock (n = 0) 01: PCLK/4 clock 10: PCLK/16 clock 11: PCLK/64 clock */
- R_SCI4->SMR_b.MP = 0; /*0: Disable multi-processor communications function 1: Enable multi-processor communications function */
- R_SCI4->SMR_b.STOP = 0; /*0: 1 stop bit 1: 2 stop bits */
- R_SCI4->SMR_b.PM = 0; /* 0: Even parity 1: Odd parity */
- R_SCI4->SMR_b.PE = 0; /* 0: Parity Disable 1: Parity Enable */
- R_SCI4->SMR_b.CHR = 0; /* SCMR.CHR1=0: 0-9bits 1-9bits SCMR.CHR1=1: 0-8bits 1-7bits */
- R_SCI4->SMR_b.CM = 0; /* 0: Asynchronous mode or simple IIC mode 1: Clock synchronous mode or simple SPI mode*/
-
- R_SCI4->SCR_b.CKE = 0; /*1 Clock Enable 0 Clock Disable*/
- R_SCI4->SCR_b.TEIE = 0; /* 0: Disable SCIn_TEI interrupt requests 1: Enable SCIn_TEI interrupt requests */
- R_SCI4->SCR_b.MPIE = 0;
- R_SCI4->SCR_b.RIE = 1;
- R_SCI4->SCR_b.TIE = 0;
-
- R_SCI4->FCR_b.FM = 1; /* 0: Non-FIFO mode. 1: FIFO mode. */
- R_SCI4->FCR_b.RFRST = 1; /* 0: Do not reset FRDRHL 1: Reset FRDRHL */
- R_SCI4->FCR_b.RFRST = 0;
- R_SCI4->FCR_b.TFRST = 1; /* 0: Do not reset FTDRHL 1: Reset FTDRHL */
- R_SCI4->FCR_b.TFRST = 0;
- R_SCI4->FCR_b.DRES = 0; /*Receive Data Ready Error Select Selects the interrupt requested when detecting receive data ready. 0: Receive data full interrupt (SCIn_RXI) 1: Receive error interrupt (SCIn_ERI) */
- R_SCI4->FCR_b.TTRG = 1; /* Transmit FIFO Data Trigger Number */
- R_SCI4->FCR_b.RTRG = 1; /* Receive FIFO Data Trigger Number */
- R_SCI4->FCR_b.RSTRG = 0; /* RTS Output Active Trigger Number Select */
-
- R_SCI4->SEMR_b.BRME = 1;
- R_SCI4->SEMR_b.ABCS = 0;
- R_SCI4->SEMR_b.BGDM = 0;
- R_SCI4->SEMR_b.ABCSE = 0;
- /*
- * set baud
- * PCLK/(64*2^(2*n-1))*(256/M)*B - 1 n=0 CKS[1:0]=0
- */
- R_SCI4->BRR = clk_get_pclka()/(32*cfg->baud) - 1;
- R_SCI4->MDDR = 256;
- /*
- * enable
- */
- R_SCI4->SCR_b.RE = 1;
- R_SCI4->SCR_b.TE = 1;
- break;
- case HAL_UART_9:
- /* Enable CLK */
- R_MSTP->MSTPCRB_b.MSTPB22 = 0; /* SCI9 */
-
- /*P109 TXD9 PSEL:5
- *P110 RXD9 PSEL:5
- */
- R_PMISC->PWPR_b.B0WI = 0;
- R_PMISC->PWPR_b.PFSWE = 1;
-
- R_PFS->PORT[1].PIN[10].PmnPFS_b.PODR = 1; /*0: Low output 1: High output */
- //R_PFS->PORT[1].PIN[10].PmnPFS_b.PIDR /*0: Low level 1: High level */
- R_PFS->PORT[1].PIN[10].PmnPFS_b.PDR = 0; /*0: Input (functions as an input pin) 1: Output (functions as an output pin) */
- R_PFS->PORT[1].PIN[10].PmnPFS_b.PCR = 1; /*0: Disable input pull-up 1: Enable input pull-up */
- //R_PFS->PORT[1].PIN[10].PmnPFS_b.PIM /* This bit is read as 0. The write value should be 0. */
- R_PFS->PORT[1].PIN[10].PmnPFS_b.NCODR = 0; /* 0: CMOS output 1: NMOS open-drain output */
- R_PFS->PORT[1].PIN[10].PmnPFS_b.DSCR = 3; /* 00: Low drive 01: Middle drive 10: Setting prohibited 11: High drive */
- R_PFS->PORT[1].PIN[10].PmnPFS_b.EOFR = 0; /* 00: Don't care 01: Detect rising edge 01: Detect rising edge 11: Detect both edges*/
- R_PFS->PORT[1].PIN[10].PmnPFS_b.ISEL = 0; /* 0: Not used as an IRQn input pin 1: Used as an IRQn input pin */
- R_PFS->PORT[1].PIN[10].PmnPFS_b.ASEL = 0; /* 0: Not used as an analog pin 1: Used as an analog pin */
- R_PFS->PORT[1].PIN[10].PmnPFS_b.PMR = 1; /* 0: Used as a general I/O pin 1: Used as an I/O port for peripheral functions */
- R_PFS->PORT[1].PIN[10].PmnPFS_b.PSEL = 5; /* Peripheral Select */
-
- R_PFS->PORT[1].PIN[9].PmnPFS_b.PODR = 1; /*0: Low output 1: High output */
- //R_PFS->PORT[1].PIN[9].PmnPFS_b.PIDR /*0: Low level 1: High level */
- R_PFS->PORT[1].PIN[9].PmnPFS_b.PDR = 1; /*0: Input (functions as an input pin) 1: Output (functions as an output pin) */
- R_PFS->PORT[1].PIN[9].PmnPFS_b.PCR = 1; /*0: Disable input pull-up 1: Enable input pull-up */
- //R_PFS->PORT[1].PIN[9].PmnPFS_b.PIM /* This bit is read as 0. The write value should be 0. */
- R_PFS->PORT[1].PIN[9].PmnPFS_b.NCODR = 0; /* 0: CMOS output 1: NMOS open-drain output */
- R_PFS->PORT[1].PIN[9].PmnPFS_b.DSCR = 3; /* 00: Low drive 01: Middle drive 10: Setting prohibited 11: High drive */
- R_PFS->PORT[1].PIN[9].PmnPFS_b.EOFR = 0; /* 00: Don't care 01: Detect rising edge 01: Detect rising edge 11: Detect both edges*/
- R_PFS->PORT[1].PIN[9].PmnPFS_b.ISEL = 0; /* 0: Not used as an IRQn input pin 1: Used as an IRQn input pin */
- R_PFS->PORT[1].PIN[9].PmnPFS_b.ASEL = 0; /* 0: Not used as an analog pin 1: Used as an analog pin */
- R_PFS->PORT[1].PIN[9].PmnPFS_b.PMR = 1; /* 0: Used as a general I/O pin 1: Used as an I/O port for peripheral functions */
- R_PFS->PORT[1].PIN[9].PmnPFS_b.PSEL = 5; /* Peripheral Select */
-
- R_PMISC->PWPR_b.PFSWE = 0;
- R_PMISC->PWPR_b.B0WI = 1;
-
- /*
- * set param
- */
- R_SCI9->SMR_b.CKS = 0; /* 00: PCLK clock (n = 0) 01: PCLK/4 clock 10: PCLK/16 clock 11: PCLK/64 clock */
- R_SCI9->SMR_b.MP = 0; /*0: Disable multi-processor communications function 1: Enable multi-processor communications function */
- R_SCI9->SMR_b.STOP = 0; /*0: 1 stop bit 1: 2 stop bits */
- R_SCI9->SMR_b.PM = 0; /* 0: Even parity 1: Odd parity */
- R_SCI9->SMR_b.PE = 0; /* 0: Parity Disable 1: Parity Enable */
- R_SCI9->SMR_b.CHR = 0; /* SCMR.CHR1=0: 0-9bits 1-9bits SCMR.CHR1=1: 0-8bits 1-7bits */
- R_SCI9->SMR_b.CM = 0; /* 0: Asynchronous mode or simple IIC mode 1: Clock synchronous mode or simple SPI mode*/
-
- R_SCI9->SCR_b.CKE = 0; /*1 Clock Enable 0 Clock Disable*/
- R_SCI9->SCR_b.TEIE = 0; /* 0: Disable SCIn_TEI interrupt requests 1: Enable SCIn_TEI interrupt requests */
- R_SCI9->SCR_b.MPIE = 0;
- R_SCI9->SCR_b.RIE = 1;
- R_SCI9->SCR_b.TIE = 0;
-
- R_SCI9->FCR_b.FM = 1; /* 0: Non-FIFO mode. 1: FIFO mode. */
- R_SCI9->FCR_b.RFRST = 1; /* 0: Do not reset FRDRHL 1: Reset FRDRHL */
- R_SCI9->FCR_b.RFRST = 0;
- R_SCI9->FCR_b.TFRST = 1; /* 0: Do not reset FTDRHL 1: Reset FTDRHL */
- R_SCI9->FCR_b.TFRST = 0;
- R_SCI9->FCR_b.DRES = 0; /*Receive Data Ready Error Select Selects the interrupt requested when detecting receive data ready. 0: Receive data full interrupt (SCIn_RXI) 1: Receive error interrupt (SCIn_ERI) */
- R_SCI9->FCR_b.TTRG = 1; /* Transmit FIFO Data Trigger Number */
- R_SCI9->FCR_b.RTRG = 1; /* Receive FIFO Data Trigger Number */
- R_SCI9->FCR_b.RSTRG = 0; /* RTS Output Active Trigger Number Select */
-
- R_SCI9->SEMR_b.BRME = 1;
- R_SCI9->SEMR_b.ABCS = 0;
- R_SCI9->SEMR_b.BGDM = 0;
- R_SCI9->SEMR_b.ABCSE = 0;
- /*
- * set baud
- * PCLK/(64*2^(2*n-1))*(256/M)*B - 1 n=0 CKS[1:0]=0
- */
- R_SCI9->BRR = clk_get_pclka()/(32*cfg->baud) - 1;
- R_SCI9->MDDR = 256;
- /*
- * enable
- */
- R_SCI9->SCR_b.RE = 1;
- R_SCI9->SCR_b.TE = 1;
- break;
- default:
- res = -1;
- break;
- }
- return res;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_EnableTx(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable)
- * brief 发送使能.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] type 处理方式 ref HAL_UART_TYPE_e.
- * param[in] enable 使能或者禁能 ref HAL_UART_ENABLE_e.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_EnableTx(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable)
- {
- return 0;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_EnableRx(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable)
- * brief 接收使能.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] type 处理方式 ref HAL_UART_TYPE_e.
- * param[in] enable 使能或者禁能 ref HAL_UART_ENABLE_e.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_EnableRx(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable)
- {
- return 0;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_EnableRxErr(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable)
- * brief 接收错误中断使能.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] type 处理方式 ref HAL_UART_TYPE_e.
- * param[in] enable 使能或者禁能 ref HAL_UART_ENABLE_e.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_EnableRxErr(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable)
- {
- return 0;
- }
- /**
- *****************************************************************************
- * fn int HAL_UART_DeInit(HAL_UART_ID_e id)
- * brief 解除UART模块,关闭模块.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * retval 0 成功.
- * retval -1 失败.
- *****************************************************************************
- */
- int HAL_UART_DeInit(HAL_UART_ID_e id)
- {
- return 0;
- }
复制代码
hal_uart.h
- #ifndef __HAL_UART_H
- #define __HAL_UART_H
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- /** addtogroup HAL
- * {
- */
-
- /** addtogroup HAL_UART 硬件抽象层(HAL)串口模块(UART)
- * {
- */
- /*****************************************************************************
- * *
- * 数据结构描述 *
- * *
- ****************************************************************************/
-
- /** defgroup HAL_UART_data 硬件抽象层(HAL)串口模块(UART)数据结构
- * {
- */
-
-
- /**
- * enum hal_uart_txstate
- * UART 发送状态.
- */
- enum hal_uart_txstate
- {
- HAL_UART_TXIDLE=0, /**< UART 发送空闲 */
- HAL_UART_TXBUSY=1, /**< UART 正在发送 */
- };
- typedef enum hal_uart_txstate HAL_UART_TXSTATE_e; /**< UART 发送状态枚举定义 */
-
-
- /**
- * enum hal_uart_enable
- * UART 使能枚举定义.
- */
- enum hal_uart_enable
- {
- HAL_UART_DISABLE=0, /**< UART 不使能 */
- HAL_UART_ENABLE=1, /**< UART 使能 */
- };
- typedef enum hal_uart_enable HAL_UART_ENABLE_e; /**< UART 使能枚举定义 */
-
-
- /**
- * enum hal_uart_type
- * UART 处理方式枚举定义.
- */
- enum hal_uart_type
- {
- HAL_UART_INTERRUPT=0, /**< UART 中断方式 */
- HAL_UART_CHECK=1, /**< UART 查询方式 */
- };
- typedef enum hal_uart_type HAL_UART_TYPE_e; /**< UART 处理方式枚举定义 */
-
-
-
- /**
- * enum hal_uart_id
- * UART ID枚举定义.
- * note id从0开始连续递增,HAL预留足够多的id号n
- * 实际用到的id号由BSP硬件资源实现决定.
- */
- enum hal_uart_id
- {
- HAL_UART_0=0, /**< UART ID0 */
- HAL_UART_1=1, /**< UART ID1 */
- HAL_UART_2=2, /**< UART ID2 */
- HAL_UART_3=3, /**< UART ID3 */
- HAL_UART_4=4, /**< UART ID4 */
- HAL_UART_5=5, /**< UART ID5 */
- HAL_UART_6=6, /**< UART ID6 */
- HAL_UART_7=7, /**< UART ID7 */
- HAL_UART_8=8, /**< UART ID8 */
- HAL_UART_9=8, /**< UART ID9 */
- HAL_UART_MAX=8, /**< UART 个数 */
- HAL_UART_INV=0xFF, /**< 无效ID */
- };
- typedef enum hal_uart_id HAL_UART_ID_e; /**< UART ID枚举定义 */
-
-
- /**
- * enum hal_uart_parity
- * UART数据奇偶校验枚举定义.
- * note HAL描述了所有标准校验方式,n
- * 实际用到的校验由BSP硬件资源实现决定.
- */
- enum hal_uart_parity
- {
- HAL_UART_PARITY_NONE=0, /**< UART无检验 */
- HAL_UART_PARITY_EVEN=1, /**< UART偶校验 */
- HAL_UART_PARITY_ODD=2, /**< UART奇校验 */
- HAL_UART_PARITY_HIG=3, /**< UART校验固定1 */
- HAL_UART_PARITY_LOW=4, /**< UART校验固定0 */
- };
- typedef enum hal_uart_parity HAL_UART_PARITY_e; /**< UART数据奇偶校验枚举定义 */
-
-
- /**
- * enum hal_uart_datalen
- * UART数据长度枚举定义.
- * note HAL描述了所有标准数据长度,n
- * 实际用到的数据长度由BSP硬件资源实现决定.
- */
- enum hal_uart_datalen
- {
- HAL_UART_DATA_9=9, /**< UART 9位数据 */
- HAL_UART_DATA_8=8, /**< UART 8位数据 */
- HAL_UART_DATA_7=7, /**< UART 7位数据 */
- HAL_UART_DATA_6=6, /**< UART 6位数据 */
- HAL_UART_DATA_5=5, /**< UART 5位数据 */
- };
- typedef enum hal_uart_datalen HAL_UART_DATALEN_e; /**< UART数据长度枚举定义 */
-
-
- /**
- * enum hal_uart_stopb
- * UART停止位枚举定义.
- * note HAL描述了所有标准停止位长度,n
- * 实际用到的停止位长度由BSP硬件资源实现决定.
- */
- enum hal_uart_stopb
- {
- HAL_UART_STOPB_1P5=0, /**< UART 1.5位停止位 */
- HAL_UART_STOPB_1=1, /**< UART 1位停止位 */
- HAL_UART_STOPB_2=2, /**< UART 2位停止位 */
- };
- typedef enum hal_uart_stopb HAL_UART_STOPB_e; /**< UART停止位枚举定义 */
-
-
- /**
- * enum hal_uart_baud
- * UART波特率枚举定义.
- * note HAL描述了常见波特率,n
- * 实际支持的波特率由BSP硬件资源实现决定.
- */
- enum hal_uart_baud
- {
- HAL_UART_BAUD_600=600, /**< UART波特率600 */
- HAL_UART_BAUD_1200=1200, /**< UART波特率1200 */
- HAL_UART_BAUD_2400=2400, /**< UART波特率2400 */
- HAL_UART_BAUD_4800=4800, /**< UART波特率4800 */
- HAL_UART_BAUD_9600=9600, /**< UART波特率9600 */
- HAL_UART_BAUD_19200=19200, /**< UART波特率19200 */
- HAL_UART_BAUD_38400=38400, /**< UART波特率38400 */
- HAL_UART_BAUD_57600=57600, /**< UART波特率38400 */
- HAL_UART_BAUD_115200=115200, /**< UART波特率115200 */
- HAL_UART_BAUD_256000=256000, /**< UART波特率256000 */
- };
- typedef enum hal_uart_baud HAL_UART_BAUD_e; /**< UART波特率枚举定义 */
-
- typedef struct hal_uart_cfg HAL_UART_CFG_t; /**< UART配置结构体 */
- /**
- * struct hal_uart_cfg
- * UART配置结构体.
- */
- struct hal_uart_cfg
- {
- HAL_UART_ID_e id; /**< UART id */
- HAL_UART_DATALEN_e datalen; /**< UART数据长度*/
- HAL_UART_PARITY_e parity; /**< UART校验 */
- HAL_UART_STOPB_e stopb; /**< UART停止位 */
- HAL_UART_BAUD_e baud; /**< UART波特率 */
- };
-
- /**
- * enum hal_uart_err
- * UART错误类型枚举定义.
- */
- enum hal_uart_err
- {
- HAL_UART_ERR_NONE=0, /**< UART无错误 */
- HAL_UART_ERR_PER=1, /**< UART校验错误 */
- HAL_UART_ERR_FER=2, /**< UART帧错误 */
- HAL_UART_ERR_ORER=4, /**< UART溢出错误 */
- };
- typedef enum hal_uart_err HAL_UART_ERR_e; /**< UART错误类型枚举定义 */
-
- /**
- * typedef HAL_UART_ISRCallBack
- * 中断服务回调函数.
- * - rxerrfun输入错误回调函数时,param指向错误码字节数据,不需要返回值.
- * - rxfun输入缓冲满回调函数时,param指向读到的字节数据,不需要返回值.
- * - txfun发送缓冲空回调函数,需要往param写需要发送的字节,返回值0表示还有数据需要发送 返回其他值标志本次为最后一字节数据.
- * - txcmpfun发送完回调函数,需要往param写需要发送的字节,返回值0表示还有数据需要发送 返回其他值标志本次为最后一字节数据.
- */
- typedef int (*HAL_UART_ISRCallBack)(unsigned char* param) ; /**< 中断服务回调函数 */
- typedef struct hal_uart_isrcallback HAL_UART_ISRCALLBACK_t; /**< 中断服务回调函数结构体 */
- /**
- * struct hal_uart_isrcallback
- * UART回调函数结构体.
- */
- struct hal_uart_isrcallback
- {
- HAL_UART_ID_e id; /**< UART id */
- HAL_UART_ISRCallBack rxerrfun; /**< 输入错误回调函数 */
- HAL_UART_ISRCallBack rxfun; /**< 输入缓冲满回调函数 */
- HAL_UART_ISRCallBack txfun; /**< 发送缓冲空回调函数 */
- HAL_UART_ISRCallBack txcmpfun; /**< 发送完回调函数 */
- };
- /**
- * }
- */
- /*****************************************************************************
- *
- * 接口函数描述
- *
- ****************************************************************************/
- /** defgroup HAL_UART_if 硬件抽象层(HAL)串口模块(UART)接口
- * {
- */
- /**
- *****************************************************************************
- * fn int HAL_UART_Init(HAL_UART_ID_e id)
- * brief 初始化UART模块,完成模块相关必要的初始化配置.
- * note 使用UART前必须调用,所有UART按默认配置(BSP实现).
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * retval 0 初始化成功.
- * retval -1 初始化失败.
- *****************************************************************************
- */
- int HAL_UART_Init(HAL_UART_ID_e id);
- /**
- *****************************************************************************
- * fn int HAL_UART_CheckSend(HAL_UART_ID_e id,unsigned char byte)
- * brief 查询的方式发送一个字节.
- * note 阻塞发送,直到发送完才会返回.
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] byte 需要发送的字节.
- * retval 0 发送成功.
- * retval 其他值 发送失败(实际上没有发送完会阻塞所以不会返回其他值).
- *****************************************************************************
- */
- int HAL_UART_CheckSend(HAL_UART_ID_e id,unsigned char byte);
- /**
- *****************************************************************************
- * fn int HAL_UART_CheckRead(HAL_UART_ID_e id,unsigned char* byte);
- * brief 查询的方式读一个字节.
- * note 阻塞读,直到有数据才会返回.
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] byte 存储读到的字节.
- * retval 0 读成功.
- * retval 其他值 读失败(实际上读不到数据会阻塞所以不会返回其他值).
- *****************************************************************************
- */
- int HAL_UART_CheckRead(HAL_UART_ID_e id,unsigned char* byte);
- /**
- *****************************************************************************
- * fn int HAL_UART_Send(HAL_UART_ID_e id,unsigned char byte)
- * brief 直接发送一个字节.
- * note 直接发送,直接往硬件发送缓冲写字节立即返回.
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] byte 需要发送的字节.
- * retval 0 发送成功.
- * retval 其他值 发送失败(实际上不会返回其他值).
- *****************************************************************************
- */
- int HAL_UART_Send(HAL_UART_ID_e id,unsigned char byte);
- /**
- *****************************************************************************
- * fn int HAL_UART_Read(HAL_UART_ID_e id,unsigned char* byte);
- * brief 直接读一个字节.
- * note 直接读,直接读硬件缓冲立即返回.
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] byte 存储读到的字节.
- * retval 0 读成功.
- * retval 其他值 读失败(实际上不会返回其他值).
- *****************************************************************************
- */
- int HAL_UART_Read(HAL_UART_ID_e id,unsigned char* byte);
- /**
- *****************************************************************************
- * fn int HAL_UART_SetTxISRCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- * brief 设置发送缓冲区空中断服务回调函数.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] callbackfun 回调函数.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_SetTxISRCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun);
- /**
- *****************************************************************************
- * fn int HAL_UART_SetTxCmpISRCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- * brief 设置发送完中断服务回调函数.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] callbackfun 回调函数.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_SetTxCmpISRCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun);
- /**
- *****************************************************************************
- * fn int HAL_UART_SetRxCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- * brief 设置接收缓冲满中断服务回调函数.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] callbackfun 回调函数.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_SetRxCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun);
- /**
- *****************************************************************************
- * fn int HAL_UART_SetRxErrCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun)
- * brief 设置接收错误中断服务回调函数.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] callbackfun 回调函数.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_SetRxErrCallBack(HAL_UART_ID_e id,HAL_UART_ISRCallBack callbackfun);
- /**
- *****************************************************************************
- * fn int HAL_UART_SetCfg(HAL_UART_ID_e id,HAL_UART_CFG_t* cfg)
- * brief 配置UART参数.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] cfg 指向配置参数结构体 ref HAL_UART_CFG_t.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_SetCfg(HAL_UART_ID_e id,HAL_UART_CFG_t* cfg);
- /**
- *****************************************************************************
- * fn int HAL_UART_EnableTx(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable)
- * brief 发送使能.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] type 处理方式 ref HAL_UART_TYPE_e.
- * param[in] enable 使能或者禁能 ref HAL_UART_ENABLE_e.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_EnableTx(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable);
- /**
- *****************************************************************************
- * fn int HAL_UART_EnableRx(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable)
- * brief 接收使能.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] type 处理方式 ref HAL_UART_TYPE_e.
- * param[in] enable 使能或者禁能 ref HAL_UART_ENABLE_e.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_EnableRx(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable);
- /**
- *****************************************************************************
- * fn int HAL_UART_EnableRxErr(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable)
- * brief 接收错误中断使能.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * param[in] type 处理方式 ref HAL_UART_TYPE_e.
- * param[in] enable 使能或者禁能 ref HAL_UART_ENABLE_e.
- * retval 0 设置成功.
- * retval 其他值 设置失败.
- *****************************************************************************
- */
- int HAL_UART_EnableRxErr(HAL_UART_ID_e id,HAL_UART_TYPE_e type,HAL_UART_ENABLE_e enable);
- /**
- *****************************************************************************
- * fn int HAL_UART_DeInit(HAL_UART_ID_e id)
- * brief 解除UART模块,关闭模块.
- * note .
- * param[in] id UARTid,依赖于BSP实现,ref HAL_UART_ID_e.
- * retval 0 成功.
- * retval -1 失败.
- *****************************************************************************
- */
- int HAL_UART_DeInit(HAL_UART_ID_e id);
- /**
- * }
- */
- /**
- * }
- */
- /**
- * }
- */
- /**
- * }
- */
- #ifdef __cplusplus
- }
- #endif
- #endif
复制代码
driver_uart.c
- #define DRIVER_UART_GLOBALS /**< 包含driver_uart.h中的数据将会编译*/
- #include "driver_uart.h"
- #include "osapi.h"
-
- /*****************************************************************************
- *
- * 内部数据
- *
- ****************************************************************************/
- /*****************************************************************************
- *
- * 内部接口函数实现
- *
- ****************************************************************************/
- /*485方向控制回调函数:
- 按照一般需求最多8路串口这里实现8路,如果有更多路需求再添加即可
- */
- #if UART0_ENABLE
- static void uart0_txhook(void)
- {
- /*无效电平发送*/
- }
- static void uart0_rxhook(void)
- {
- /*有效电平接收*/
- }
- #endif
- #if UART4_ENABLE
- static void uart4_txhook(void)
- {
- /*无效电平发送*/
- }
- static void uart4_rxhook(void)
- {
- /*有效电平接收 */
- }
- #endif
- #if UART9_ENABLE
- static void uart9_txhook(void)
- {
- /*无效电平发送*/
- }
- static void uart9_rxhook(void)
- {
- /*有效电平接收 */
- }
- #endif
- /**
- *****************************************************************************
- * fn static int rx_fifo_in(driver_uart_t *p, unsigned char data)
- * brief 写数据到接收缓冲区.
- * note 接收中断服务函数调用该函数写数据到接收缓冲区,缓冲区满不写入.
- * param[in] p 指向uart结构体实例的指针 ref driver_uart_t
- * param[in] data 指向要写到缓冲区的数据
- *****************************************************************************
- */
- static int rx_fifo_in(driver_uart_t *p, unsigned char data)
- {
- if(p==0)
- {
- return 0;
- }
- /*缓冲区未满写入数据*/
- if (p->rx_len < (p->rxbuf_len/sizeof(p->rx_buf[0])))
- {
- p->rx_buf[p->rx_in++] = data; /*写入数据,写入指针递增*/
- p->rx_in %= p->rxbuf_len/sizeof(p->rx_buf[0]); /*边界处理,实现圆形缓冲区*/
- p->rx_len++; /*数据个数递增*/
- return 0;
- }
- else
- {
- return -1;
- }
- }
- /**
- *****************************************************************************
- * fn static unsigned char rx_fifo_out(driver_uart_t *p, unsigned int timeout, unsigned char *perro)
- * brief 从接收缓冲区读数据.
- * note 应用函数调用该函数从接收缓冲区读数据,可以指定超时时间.
- * param[in] p 指向uart结构体实例的指针 ref driver_uart_t
- * param[in] timeout 指定超时时间 0表示一直等待
- * param[in] perro 错误码0表示读到了数据 1表示没有读到数据
- * retval unsigned char 读到的字节数据.
- *****************************************************************************
- */
- static unsigned char rx_fifo_out(driver_uart_t *p, unsigned int timeout, int *perro)
- {
- unsigned char data = 0;
- if(p==0)
- {
- *perro = 1;
- return 0;
- }
- OSCriticalAlloc();
- /*timeout==0 表示一直等待直到有数据*/
- if (timeout == 0)
- {
- while(p->rx_len == 0)
- {
- OsTimeDelay(DRIVER_UART_DELAY_CHECK); /*延时*/
- }
- }
- else /*timeout!=0 表示等待指定超时时间*/
- {
- while (timeout != 0)
- {
- if (p->rx_len == 0)
- {
- /*如果无数据,延时指定时间间隔*/
- if (timeout >= DRIVER_UART_DELAY_CHECK)
- {
- timeout -= DRIVER_UART_DELAY_CHECK;
- OsTimeDelay(DRIVER_UART_DELAY_CHECK);
- }
- else
- {
- /*不足一个时间间隔延时剩余时间*/
- OsTimeDelay(timeout);
- timeout = 0;
- }
- }
- else
- {
- break;
- }
- }
- }
- /*临界段处理 防止此时中断在操作缓冲区*/
- OSCriticalEnter();
- if (p->rx_len != 0)
- {
- /*从缓冲区读出数据*/
- p->rx_len--;
- data = p->rx_buf[p->rx_out++];
- p->rx_out %= p->rxbuf_len/sizeof(p->rx_buf[0]);
- *perro = 0;
- }
- else
- {
- *perro = 1;
- }
- OSCriticalExit();
- return data;
- }
- /**
- *****************************************************************************
- * fn static int tx_fifo_in(driver_uart_t *p, unsigned int timeout, unsigned char data,unsigned char *perro)
- * brief 写数据到发送缓冲区.
- * note 应用调用该函数调写数据到发送缓冲区,缓冲区满等待.
- * param[in] p 指向uart结构体实例的指针 ref driver_uart_t
- * param[in] timeout 设定超时时间 0表示一直等待
- * param[in] data 指向要写到缓冲区的数据
- * retval 0 写成功
- * retval 1 写失败
- *****************************************************************************
- */
- static int tx_fifo_in(driver_uart_t *p, unsigned char data, unsigned int timeout)
- {
- /*注意确保p缓冲区的读写处于临界段保护 */
- int ret=0;
- if(p==0)
- {
- return 1;
- }
- OSCriticalAlloc();
- if (timeout == 0)
- {
-
- while(1)
- {
- OSCriticalEnter();
- if(p->tx_len < (p->txbuf_len/sizeof(p->tx_buf[0])))
- {
- /*没有满则写入数据*/
- p->tx_buf[p->tx_in++] = data;
- p->tx_in %= p->txbuf_len/sizeof(p->tx_buf[0]);
- p->tx_len++;
- OSCriticalExit();
- break;
- }
- else
- {
- /*满则等待*/
- OSCriticalExit();
- OsTimeDelay(DRIVER_UART_DELAY_CHECK); /*延时*/
- }
- }
- }
- while (timeout != 0)
- {
- OSCriticalEnter();
- if (p->tx_len < (p->txbuf_len/sizeof(p->tx_buf[0])))
- {
- /*没有满则写入数据*/
- p->tx_buf[p->tx_in++] = data;
- p->tx_in %= p->txbuf_len/sizeof(p->tx_buf[0]);
- p->tx_len++;
- OSCriticalExit();
- ret = 0; /*设置正确返回值*/
- break;
- }
- else
- {
- OSCriticalExit();
- /*如果无数据,延时指定时间间隔*/
- if (timeout >= DRIVER_UART_DELAY_CHECK)
- {
- timeout -= DRIVER_UART_DELAY_CHECK;
- OsTimeDelay(DRIVER_UART_DELAY_CHECK);
- ret = 1; /*设置超时错误 之前这里没设置ret=1 在timeout为DRIVER_UART_DELAY_CHECK的整数倍时总是会返回0*/
- }
- else
- {
- /*不足一个时间间隔延时剩余时间*/
- OsTimeDelay(timeout);
- timeout = 0;
- ret = 1; /*设置超时错误*/
- }
- }
- }
- return ret;
- }
- /**
- *****************************************************************************
- * fn static unsigned char tx_fifo_out(driver_uart_t *p, unsigned char *perro)
- * brief 从发送缓冲区读数据.
- * note 发送中断服务函数调用该函数获取发送缓冲区数据,用于发送.
- * param[in] p 指向uart结构体实例的指针 ref driver_uart_t
- * param[out] perro 错误码 0表示读到数据 1表示没有数据
- * return unsigned char perro=0时表示读到的数据
- *****************************************************************************
- */
- static unsigned char tx_fifo_out(driver_uart_t *p, int *perro)
- {
- unsigned char data = 0;
- if(p==0)
- {
- *perro = 1;
- return 0;
- }
- if (p->tx_len != 0)
- {
- if(p->tx_hook != 0)
- {
- (*(p->tx_hook))();
- }
- p->tx_len--;
- data = p->tx_buf[p->tx_out++];
- p->tx_out %= p->txbuf_len/sizeof(p->tx_buf[0]);
- *perro = 0;
- }
- else
- {
- *perro = 1;
- }
- return data;
- }
- /**
- *****************************************************************************
- * fn static int driver_uart0_send_isr(unsigned char *pdata)
- * brief 发送处理.
- * note 发送中断服务函数调用该函数,如果缓冲区空则停止发送并调用回调函数.
- * param[out] pdata 回写需要发送的数据
- * retval 0 pdata指向的数据有效(需要发送) 1无后续发送数据
- *****************************************************************************
- */
- #if UART0_ENABLE
- static int driver_uart0_send_isr(unsigned char *pdata)
- {
- int erro=0;
- unsigned char data;
- if(driver_uart_tab[0]==0)
- {
- return 1;
- }
- data = tx_fifo_out(driver_uart_tab[0], &erro);
- if (erro != 0)
- {
- /*没有获取到数据,停止发送*/
- HAL_UART_EnableTx(driver_uart_tab[0]->id,HAL_UART_INTERRUPT,HAL_UART_DISABLE);
- driver_uart_tab[0]->state = HAL_UART_TXIDLE;
- if(driver_uart_tab[0]->rx_hook != 0)
- {
- driver_uart_tab[0]->rx_hook();
- }
- return 1;
- }
- else
- {
- *pdata = data;
- return 0;
- }
- }
- #endif
- /**
- *****************************************************************************
- * fn static int driver_uart4_send_isr(unsigned char *pdata)
- * brief 发送处理.
- * note 发送中断服务函数调用该函数,如果缓冲区空则停止发送并调用回调函数.
- * param[out] pdata 回写需要发送的数据
- * retval 0 pdata指向的数据有效(需要发送) 1无后续发送数据
- *****************************************************************************
- */
- #if UART4_ENABLE
- static int driver_uart4_send_isr(unsigned char *pdata)
- {
- int erro=0;
- unsigned char data;
- if(driver_uart_tab[4]==0)
- {
- return 1;
- }
- data = tx_fifo_out(driver_uart_tab[4], &erro);
- if (erro != 0)
- {
- /*没有获取到数据,停止发送*/
- HAL_UART_EnableTx(driver_uart_tab[4]->id,HAL_UART_INTERRUPT,HAL_UART_DISABLE);
- driver_uart_tab[4]->state = HAL_UART_TXIDLE;
- if(driver_uart_tab[4]->rx_hook != 0)
- {
- driver_uart_tab[4]->rx_hook();
- }
- return 1;
- }
- else
- {
- *pdata = data;
- return 0;
- }
- }
- #endif
- /**
- *****************************************************************************
- * fn static int driver_uart9_send_isr(unsigned char *pdata)
- * brief 发送处理.
- * note 发送中断服务函数调用该函数,如果缓冲区空则停止发送并调用回调函数.
- * param[out] pdata 回写需要发送的数据
- * retval 0 pdata指向的数据有效(需要发送) 1无后续发送数据
- *****************************************************************************
- */
- #if UART9_ENABLE
- static int driver_uart9_send_isr(unsigned char *pdata)
- {
- int erro=0;
- unsigned char data;
- if(driver_uart_tab[9]==0)
- {
- return 1;
- }
- data = tx_fifo_out(driver_uart_tab[9], &erro);
- if (erro != 0)
- {
- /*没有获取到数据,停止发送*/
- HAL_UART_EnableTx(driver_uart_tab[9]->id,HAL_UART_INTERRUPT,HAL_UART_DISABLE);
- driver_uart_tab[9]->state = HAL_UART_TXIDLE;
- if(driver_uart_tab[9]->rx_hook != 0)
- {
- driver_uart_tab[9]->rx_hook();
- }
- return 1;
- }
- else
- {
- *pdata = data;
- return 0;
- }
- }
- #endif
- /**
- *****************************************************************************
- * fn static int driver_uart0_recv_isr(unsigned char* data)
- * brief 接收处理.
- * note 接收中断服务函数调用该函数,如果缓冲区满则丢弃新的数据.
- * param[out] pdata 新的数据.
- * retval 总是返回0
- *****************************************************************************
- */
- #if UART0_ENABLE
- static int driver_uart0_recv_isr(unsigned char* data)
- {
- if(driver_uart_tab[0]==0)
- {
- return 0;
- }
- driver_uart_tab[0]->rxhavedata =1;
- return rx_fifo_in(driver_uart_tab[0], *data);
- }
- #endif
- /**
- *****************************************************************************
- * fn static int driver_uart4_recv_isr(unsigned char* data)
- * brief 接收处理.
- * note 接收中断服务函数调用该函数,如果缓冲区满则丢弃新的数据.
- * param[out] pdata 新的数据.
- * retval 总是返回0
- *****************************************************************************
- */
- #if UART4_ENABLE
- static int driver_uart4_recv_isr(unsigned char* data)
- {
- if(driver_uart_tab[4]==0)
- {
- return 0;
- }
- driver_uart_tab[4]->rxhavedata =1;
- return rx_fifo_in(driver_uart_tab[4], *data);
- }
- #endif
- /**
- *****************************************************************************
- * fn static int driver_uart9_recv_isr(unsigned char* data)
- * brief 接收处理.
- * note 接收中断服务函数调用该函数,如果缓冲区满则丢弃新的数据.
- * param[out] pdata 新的数据.
- * retval 总是返回0
- *****************************************************************************
- */
- #if UART9_ENABLE
- static int driver_uart9_recv_isr(unsigned char* data)
- {
- if(driver_uart_tab[9]==0)
- {
- return 0;
- }
- driver_uart_tab[9]->rxhavedata =1;
- return rx_fifo_in(driver_uart_tab[9], *data);
- }
- #endif
- /**
- *****************************************************************************
- * fn static int driver_uart_rxerr_isr(HAL_UART_ID_e id,unsigned char *pdata)
- * brief 接收错误处理.
- * note 接收错误中断服务函数调用该函数.
- * param[in] pdata 错误码
- * retval 0 总是返回0
- *****************************************************************************
- */
- static int driver_uart_rxerr_isr(HAL_UART_ID_e id,unsigned char *pdata)
- {
- if(driver_uart_tab[id]==0)
- {
- return 0;
- }
- if(*pdata & HAL_UART_ERR_PER)
- {
- if((driver_uart_tab[id]->err & 0x000000FF) != 0x000000FF)
- {
- driver_uart_tab[id]->err = driver_uart_tab[id]->err + 1;
- }
- else
- {
- HAL_UART_EnableRxErr(id,HAL_UART_INTERRUPT,HAL_UART_DISABLE);
- HAL_UART_EnableRx(id,HAL_UART_INTERRUPT,HAL_UART_DISABLE);
- }
- }
- if(*pdata & HAL_UART_ERR_FER)
- {
- if((driver_uart_tab[id]->err & 0x0000FF00) != 0x0000FF00)
- {
- driver_uart_tab[id]->err = driver_uart_tab[id]->err + 0x100;
- }
- else
- {
- HAL_UART_EnableRxErr(id,HAL_UART_INTERRUPT,HAL_UART_DISABLE);
- HAL_UART_EnableRx(id,HAL_UART_INTERRUPT,HAL_UART_DISABLE);
- }
- }
- if(*pdata & HAL_UART_ERR_ORER)
- {
- if((driver_uart_tab[id]->err & 0x00FF0000) != 0x00FF0000)
- {
- driver_uart_tab[id]->err = driver_uart_tab[id]->err + 0x10000;
- }
- else
- {
- HAL_UART_EnableRxErr(id,HAL_UART_INTERRUPT,HAL_UART_DISABLE);
- HAL_UART_EnableRx(id,HAL_UART_INTERRUPT,HAL_UART_DISABLE);
- }
- }
- return 0;
- }
- /**
- *****************************************************************************
- * fn static int driver_uart0_rxerr_isr(unsigned char *pdata)
- * brief 接收错误处理.
- * note 接收错误中断服务函数调用该函数.
- * param[in] pdata 错误码
- * retval 0 总是返回0
- *****************************************************************************
- */
- #if UART0_ENABLE
- static int driver_uart0_rxerr_isr(unsigned char *pdata)
- {
- return driver_uart_rxerr_isr(HAL_UART_0,pdata);
- }
- #endif
- /**
- *****************************************************************************
- * fn static int driver_uart4_rxerr_isr(unsigned char *pdata)
- * brief 接收错误处理.
- * note 接收错误中断服务函数调用该函数.
- * param[in] pdata 错误码
- * retval 0 总是返回0
- *****************************************************************************
- */
- #if UART4_ENABLE
- static int driver_uart4_rxerr_isr(unsigned char *pdata)
- {
- return driver_uart_rxerr_isr(HAL_UART_4,pdata);
- }
- #endif
- /**
- *****************************************************************************
- * fn static int driver_uart9_rxerr_isr(unsigned char *pdata)
- * brief 接收错误处理.
- * note 接收错误中断服务函数调用该函数.
- * param[in] pdata 错误码
- * retval 0 总是返回0
- *****************************************************************************
- */
- #if UART9_ENABLE
- static int driver_uart9_rxerr_isr(unsigned char *pdata)
- {
- return driver_uart_rxerr_isr(HAL_UART_9,pdata);
- }
- #endif
- /*****************************************************************************
- *
- * 对外接口函数实现
- *
- ****************************************************************************/
- /**
- *****************************************************************************
- * fn static int driver_uart_init(HAL_UART_ID_e id)
- * brief 初始化串口.
- * note .
- * param[in] id 串口id ref HAL_UART_ID_e
- * retval 0 设置成功
- * retval -1参数错误
- *****************************************************************************
- */
- static int driver_uart_init(HAL_UART_ID_e id)
- {
- /*初始化端口和默认参数*/
- HAL_UART_Init(id);
- /*设置回调函数*/
- switch(id)
- {
- #if UART0_ENABLE
- case HAL_UART_0:
- HAL_UART_SetTxCmpISRCallBack(HAL_UART_0,driver_uart0_send_isr);
- HAL_UART_SetRxCallBack(HAL_UART_0,driver_uart0_recv_isr);
- HAL_UART_SetRxErrCallBack(HAL_UART_0,driver_uart0_rxerr_isr);
- break;
- #endif
- #if UART4_ENABLE
- case HAL_UART_4:
- HAL_UART_SetTxCmpISRCallBack(HAL_UART_4,driver_uart4_send_isr);
- HAL_UART_SetRxCallBack(HAL_UART_4,driver_uart4_recv_isr);
- HAL_UART_SetRxErrCallBack(HAL_UART_4,driver_uart4_rxerr_isr);
- break;
- #endif
- #if UART9_ENABLE
- case HAL_UART_9:
- HAL_UART_SetTxCmpISRCallBack(HAL_UART_9,driver_uart9_send_isr);
- HAL_UART_SetRxCallBack(HAL_UART_9,driver_uart9_recv_isr);
- HAL_UART_SetRxErrCallBack(HAL_UART_9,driver_uart9_rxerr_isr);
- break;
- #endif
- default:
- return -1;
- break;
- }
- return 0;
- }
- /**
- *****************************************************************************
- * fn unsigned int driver_uart_getrxlen(HAL_UART_ID_e id)
- * brief 获取接收缓冲区有效数据长度.
- * note .
- * param[in] id 串口id ref HAL_UART_ID_e
- * return unsigned int 接收缓冲区长度
- *****************************************************************************
- */
- unsigned int driver_uart_getrxlen(HAL_UART_ID_e id)
- {
- if(driver_uart_tab[id]==0)
- {
- return 0;
- }
- return driver_uart_tab[id]->rx_len;
- }
- /**
- *****************************************************************************
- * fn unsigned int driver_uart_flush(HAL_UART_ID_e id)
- * brief 清除缓冲区.
- * note .
- * param[in] id 串口id ref HAL_UART_ID_e
- * return int 总是返回0
- *****************************************************************************
- */
- unsigned int driver_uart_flush(HAL_UART_ID_e id)
- {
- if(driver_uart_tab[id]!=0)
- {
- driver_uart_tab[id]->rx_in = 0;
- driver_uart_tab[id]->rx_out = 0;
- driver_uart_tab[id]->rx_len = 0;
- driver_uart_tab[id]->tx_in = 0;
- driver_uart_tab[id]->tx_out = 0;
- driver_uart_tab[id]->tx_len = 0;
- driver_uart_tab[id]->err = 0x00;
- }
- return 0;
- }
- /**
- *****************************************************************************
- * fn int driver_uart_set(HAL_UART_CFG_t* cfg)
- * brief 配置串口参数.
- * note .
- * param[in] cfg 配置参数
- * return int ref HAL_UART_SetCfg 的返回值
- *****************************************************************************
- */
- int driver_uart_set(HAL_UART_CFG_t* cfg)
- {
- int ret;
- if(driver_uart_tab[cfg->id]==0)
- {
- return 0;
- }
- driver_uart_init(cfg->id);
- ret = HAL_UART_SetCfg(cfg->id,cfg);
- HAL_UART_EnableRx(cfg->id,HAL_UART_INTERRUPT,HAL_UART_ENABLE);
- driver_uart_flush(cfg->id);
- return ret;
- }
- /**
- *****************************************************************************
- * fn unsigned int driver_uart_recv(HAL_UART_ID_e id, unsigned char *pdata, unsigned int len, unsigned int timeout, int *perro)
- * brief 串口接收指定长度数据,可以设置超时时间.
- * note 应用调用该函数接收数据,如果缓冲区无数据就等待.
- * param[in] id 指定的串口id.
- * param[in] pdata 需存储接收数据的缓冲区.
- * param[in] len 接收的数据长度.
- * param[in] timeout 设置为0表示一直等到接收到指定长度数据,设置为其他值表示等待指定超时时间(单位mS)
- * param[out] perro 错误码 0表示成功 -1表示参数错误 1表示超时
- * return int 返回实际读到的数据长度
- *****************************************************************************
- */
- unsigned int driver_uart_recv(HAL_UART_ID_e id, unsigned char *pdata, unsigned int len, unsigned int timeout, int *erro)
- {
- unsigned char data=0;
- unsigned int readlen=0;
- unsigned int tmptimeout=0;
- if (id >= HAL_UART_MAX)
- {
- *erro = -1;
- return 0;
- }
- if(driver_uart_tab[id]==0)
- {
- *erro = -1;
- return 0;
- }
- if(len ==0)
- {
- *erro = -1;
- return 0;
- }
- tmptimeout = timeout;
- while(len !=0)
- {
- data = rx_fifo_out(driver_uart_tab[id], tmptimeout, erro);
- if (*erro == 0)
- {
- tmptimeout = DRIVER_UART_DELAY_FRAME;
- *pdata++ = data;
- len--;
- readlen++;
- }
- else
- {
- *erro = 1;
- break;
- }
- }
- return readlen;
- }
- /**
- *****************************************************************************
- * fn int driver_uart_send(HAL_UART_ID_e id, unsigned char *pdata, unsigned int len,unsigned int timeout,int *perro)
- * brief 串口发送指定长度数据,可以设置超时时间.
- * note 应用调用该函数发送数据,如果缓冲区满就等待.
- * param[in] id 指定的串口id.
- * param[in] pdata 需要发送的数据缓冲区.
- * param[in] len 需要发送的数据长度.
- * param[in] timeout 设置为0表示一直等到全部写入缓冲区,设置为其他值表示等待指定超时时间(单位mS)
- * param[out] perro 错误码 0表示成功 -1表示参数错误 1表示超时
- * return int 返回实际发送的数据
- *****************************************************************************
- */
- int driver_uart_send(HAL_UART_ID_e id, unsigned char *pdata, unsigned int len,unsigned int timeout,int *erro)
- {
- unsigned char full=0;
- driver_uart_t *p=0;
- unsigned char data=0;
- unsigned int sendlen=0;
- OSCriticalAlloc();
- if (id >= HAL_UART_MAX)
- {
- *erro = -1;
- return 0;
- }
- if(driver_uart_tab[id]==0)
- {
- *erro = -1;
- return 0;
- }
- if(len ==0)
- {
- *erro = -1;
- return 0;
- }
- p = (driver_uart_t *)driver_uart_tab[id];
- if(p->tx_hook !=0)
- {
- p->tx_hook(); /*调用准备发送回调函数*/
- }
- driver_uart_tab[id]->txhavedata =1;
- if(timeout == 0)
- {
- while(len !=0)
- {
- full = tx_fifo_in(p,*pdata,DRIVER_UART_DELAY_CHECK);
- if (full == 0)
- {
- pdata++;
- len--;
- sendlen++;
- }
- else
- {
- OSCriticalEnter();
- /*如果缓冲区满而且当前串口没有处于发送状态要先发送一个字节触发发送中断流*/
- if(p->state == HAL_UART_TXIDLE)
- {
- data = tx_fifo_out(p, erro);
- if(*erro == 0)
- {
- if(p->tx_hook !=0)
- {
- p->tx_hook(); /*调用准备发送回调函数*/
- }
- p->state = HAL_UART_TXBUSY; /*注意:p->state的读写需要临界保护*/
- HAL_UART_Send(p->id,data); /*注意:必须放在使能TX前,写TDR会清除TEND标志,否则使能TE会马上产生发送完中断*/
- HAL_UART_EnableTx(id,HAL_UART_INTERRUPT,HAL_UART_ENABLE);
- }
- }
- OSCriticalExit();
- OsTimeDelay(DRIVER_UART_DELAY_CHECK);
- }
- }
- *erro = 0;
- }
- else
- {
- while ((len != 0) && (timeout!=0))
- {
- full = tx_fifo_in(p,*pdata,DRIVER_UART_DELAY_CHECK);
- if (full == 0)
- {
- pdata++;
- len--;
- sendlen++;
- }
- else
- {
- OSCriticalEnter();
- /*如果缓冲区满而且当前串口没有处于发送状态要先发送一个字节触发发送中断流*/
- if(p->state == HAL_UART_TXIDLE)
- {
- data = tx_fifo_out(p, erro);
- if(*erro == 0)
- {
- if(p->tx_hook !=0)
- {
- p->tx_hook(); /*调用准备发送回调函数*/
- }
- p->state = HAL_UART_TXBUSY; /*注意:p->state的读写需要临界保护*/
- HAL_UART_Send(p->id,data); /*注意:必须放在使能TX前,写TDR会清除TEND标志,否则使能TE会马上产生发送完中断*/
- HAL_UART_EnableTx(id,HAL_UART_INTERRUPT,HAL_UART_ENABLE);
- }
- OSCriticalExit();
- }
- else /*如果当前处于发送状态*/
- {
- OSCriticalExit();
- /*如果缓冲区满而且串口处于发送状态则延时指定时间间隔等待中断发送完*/
- if (timeout >= DRIVER_UART_DELAY_CHECK)
- {
- timeout -= DRIVER_UART_DELAY_CHECK;
- OsTimeDelay(DRIVER_UART_DELAY_CHECK);
- }
- else
- {
- /*不足一个时间间隔延时剩余时间*/
- OsTimeDelay(timeout);
- timeout = 0;
- }
- }
- }
- }
- /*如果没发送完设置超时错误码*/
- if(len != 0)
- {
- *erro = 1;
- }
- }
-
- OSCriticalEnter();
- /*如果缓冲区有数据而且当前串口没有处于发送状态要先发送一个字节触发发送中断流*/
- if((p->state == HAL_UART_TXIDLE) && (p->tx_len!=0))
- {
- data = tx_fifo_out(p, erro);
- if(*erro == 0)
- {
- if(p->tx_hook !=0)
- {
- p->tx_hook(); /*调用准备发送回调函数*/
- }
- p->state = HAL_UART_TXBUSY; /*注意:p->state的读写需要临界保护*/
- #ifdef FM33A
- HAL_UART_EnableTx(id,HAL_UART_INTERRUPT,HAL_UART_ENABLE);
- HAL_UART_Send(p->id,data); /*注意:必须放在使能TX后,否则使能TE会马上清除刚写如的数据,不产生中断 这里与k20等芯片不同*/
- #else
- HAL_UART_Send(p->id,data); /*注意:必须放在使能TX前,写TDR会清除TEND标志,否则使能TE会马上产生发送完中断*/
- HAL_UART_EnableTx(id,HAL_UART_INTERRUPT,HAL_UART_ENABLE);
- #endif
- }
- }
- OSCriticalExit();
- return sendlen;
- }
- /**
- *****************************************************************************
- * fn int driver_uart_haverxdata(HAL_UART_ID_e id)
- * brief 读串口是否曾经接收到过数据.
- * note 应用调用该函数用于判断是否点亮接收指示灯.读会清除状态.
- * param[in] id 指定的串口id.
- * retval 1 串口曾经有接收数据
- * retval 0 串口没有接收数据
- *****************************************************************************
- */
- int driver_uart_haverxdata(HAL_UART_ID_e id)
- {
- unsigned char havedata=0;
- if(driver_uart_tab[id]==0)
- {
- return 0;
- }
- havedata = driver_uart_tab[id]->rxhavedata;
- driver_uart_tab[id]->rxhavedata =0;
- return havedata;
- }
- /**
- *****************************************************************************
- * fn int driver_uart_havetxdata(HAL_UART_ID_e id)
- * brief 读串口是否曾经发送过数据.
- * note 应用调用该函数用于判断是否点亮发送指示灯.读会清除状态.
- * param[in] id 指定的串口id.
- * retval 1 串口曾经有发送数据
- * retval 0 串口没有发送数据
- *****************************************************************************
- */
- int driver_uart_havetxdata(HAL_UART_ID_e id)
- {
- unsigned char havedata=0;
- if(driver_uart_tab[id]==0)
- {
- return 0;
- }
- havedata = driver_uart_tab[id]->txhavedata;
- driver_uart_tab[id]->txhavedata =0;
- return havedata;
- }
- /**
- *****************************************************************************
- * fn int driver_uart_geterr(HAL_UART_ID_e id,unsigned int* err)
- * brief 读串口错误状态字.
- * note 应用调用该函数用于判断串口是否异常,如果err的低三个字节有任意个字节为FF则表示异常需要处理.
- * param[in] id 指定的串口id ref HAL_UART_ID_e .
- * param[out] err 存储错误字
- 0xxxxxxxFF表示校验错误
- 0xxxxxFFxx表示帧错误
- 0xxxFF00xx表示溢出错误
- * retval 0 总是返回0
- *****************************************************************************
- */
- int driver_uart_geterr(HAL_UART_ID_e id,unsigned int* err)
- {
- if(driver_uart_tab[id]==0)
- {
- return 0;
- }
- *err = driver_uart_tab[id]->err;
- return 0;
- }
复制代码
driver_uart.h
- #ifndef __DRIVER_UART_H
- #define __DRIVER_UART_H
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- #include "hal_uart.h"
- /** addtogroup DRIVER 驱动层(DRIVER)
- * {
- */
-
- /** addtogroup DRIVER_UART 驱动层(DRIVER)串口模块(UART)
- * {
- */
- /*****************************************************************************
- * *
- * 数据结构描述 *
- * *
- ****************************************************************************/
- /** defgroup DRIVER_UART_data 驱动层(DRIVER)串口模块(UART)数据结构
- * {
- */
-
- #define UART0_ENABLE 1 /**< 通道0 使能 */
- #define UART4_ENABLE 1 /**< 通道4 使能 */
- #define UART9_ENABLE 1 /**< 通道9 使能 */
- #define DRIVER_UART0_TXBUF_SIZE 64 /**< UART0发送缓冲区大小 */
- #define DRIVER_UART0_RXBUF_SIZE 128 /**< UART0接收缓冲区大小 */
- #define DRIVER_UART4_TXBUF_SIZE 64 /**< UART4发送缓冲区大小 */
- #define DRIVER_UART4_RXBUF_SIZE 128 /**< UART4接收缓冲区大小 */
- #define DRIVER_UART9_TXBUF_SIZE 64 /**< UART9发送缓冲区大小 */
- #define DRIVER_UART9_RXBUF_SIZE 128 /**< UART9接收缓冲区大小 */
- #define DRIVER_UART_DELAY_FIFO (5) /**< 缓冲区操作延时时间 */
- #define DRIVER_UART_DELAY_CHECK (1) /**< 缓冲区延时查询时间间隔 */
- #define DRIVER_UART_DELAY_FRAME (5) /**< 字节间距大于该值认为帧结束 */
-
- typedef void (*driver_uart_hook)(void); /**< 发送/接收回调函数 */
- /**
- * struct driver_uart_t
- * UART驱动配置结构体.
- */
- typedef struct
- {
- HAL_UART_ID_e id; /**< UART id */
- unsigned int rx_in; /**< 接收缓冲区写入指针 */
- unsigned int rx_out; /**< 接收缓冲区读出指针 */
- unsigned int rx_len; /**< 接收缓冲区有效数据大小 */
- unsigned int tx_in; /**< 发送缓冲区写入指针 */
- unsigned int tx_out; /**< 发送缓冲区读出指针 */
- unsigned int tx_len; /**< 发送缓冲区有效数据大小 */
- unsigned short rxbuf_len; /**< 接收缓冲区大小 */
- unsigned short txbuf_len; /**< 发送缓冲区大小 */
- driver_uart_hook tx_hook; /**< 准备发送回调函数 */
- driver_uart_hook rx_hook; /**< 发送完转接收回调函数 */
- unsigned char *rx_buf; /**< 接收缓冲区 */
- unsigned char *tx_buf; /**< 发送缓冲区 */
- unsigned int bit_len; /**< 用于发送完延时(有发送完中断不需要) */
- HAL_UART_TXSTATE_e state; /**< 发送状态标志是否在发送 */
- unsigned char rxhavedata; /**< 是否有接收到数据 */
- unsigned char txhavedata; /**< 是否有发送数据 */
- unsigned int err; /**< 错误码计数器 */
- }driver_uart_t;
- /*****************************************************************************
- * *
- * 模块数据定义 *
- * *
- ****************************************************************************/
- #ifdef DRIVER_UART_GLOBALS
- /*485方向控制回调函数:
- 按照一般需求最多8路串口这里实现8路,如果有更多路需求再添加即可
- */
- static void uart9_txhook(void);
- static void uart9_rxhook(void);
- static void uart4_txhook(void);
- static void uart4_rxhook(void);
- static void uart0_txhook(void);
- static void uart0_rxhook(void);
- static unsigned char driver_uart0_rxbuf[DRIVER_UART0_RXBUF_SIZE];
- static unsigned char driver_uart0_txbuf[DRIVER_UART0_TXBUF_SIZE];
- static unsigned char driver_uart4_rxbuf[DRIVER_UART4_RXBUF_SIZE];
- static unsigned char driver_uart4_txbuf[DRIVER_UART4_TXBUF_SIZE];
- static unsigned char driver_uart9_rxbuf[DRIVER_UART4_RXBUF_SIZE];
- static unsigned char driver_uart9_txbuf[DRIVER_UART4_TXBUF_SIZE];
- static driver_uart_t driver_uart0 = {HAL_UART_0, 0,0,0, 0,0,0, sizeof(driver_uart0_rxbuf), sizeof(driver_uart0_txbuf),uart0_txhook,uart0_rxhook,driver_uart0_rxbuf, driver_uart0_txbuf, 0,HAL_UART_TXIDLE,0,0};
- static driver_uart_t driver_uart4 = {HAL_UART_0, 0,0,0, 0,0,0, sizeof(driver_uart4_rxbuf), sizeof(driver_uart4_txbuf),uart4_txhook,uart4_rxhook,driver_uart4_rxbuf, driver_uart4_txbuf, 0,HAL_UART_TXIDLE,0,0};
- static driver_uart_t driver_uart9 = {HAL_UART_0, 0,0,0, 0,0,0, sizeof(driver_uart9_rxbuf), sizeof(driver_uart9_txbuf),uart9_txhook,uart9_rxhook,driver_uart9_rxbuf, driver_uart9_txbuf, 0,HAL_UART_TXIDLE,0,0};
- static driver_uart_t *driver_uart_tab[] = {&driver_uart0, 0, 0, 0, &driver_uart4, 0, 0, 0, 0, &driver_uart9};
- #endif
- /**
- * }
- */
- /*****************************************************************************
- *
- * 接口函数描述
- *
- ****************************************************************************/
- /** defgroup DRIVER_UART_if 驱动层(DRIVER)串口模块(UART)接口
- * {
- */
-
- /**
- *****************************************************************************
- * fn unsigned int driver_uart_getrxlen(HAL_UART_ID_e id)
- * brief 获取接收缓冲区有效数据长度.
- * note .
- * param[in] id 串口id ref HAL_UART_ID_e
- * return unsigned int 接收缓冲区长度
- *****************************************************************************
- */
- unsigned int driver_uart_getrxlen(HAL_UART_ID_e id);
- /**
- *****************************************************************************
- * fn unsigned int driver_uart_flush(HAL_UART_ID_e id)
- * brief 清除缓冲区.
- * note .
- * param[in] id 串口id ref HAL_UART_ID_e
- * return int 总是返回0
- *****************************************************************************
- */
- unsigned int driver_uart_flush(HAL_UART_ID_e id);
- /**
- *****************************************************************************
- * fn int driver_uart_set(HAL_UART_CFG_t* cfg)
- * brief 配置串口参数.
- * note .
- * param[in] cfg 配置参数
- * return int ref HAL_HWT_SetCfg() 的返回值
- *****************************************************************************
- */
- int driver_uart_set(HAL_UART_CFG_t* cfg);
- /**
- *****************************************************************************
- * fn int driver_uart_recv(HAL_UART_ID_e id, unsigned char *pdata, unsigned int len, unsigned int timeout, int *perro)
- * brief 串口接收指定长度数据,可以设置超时时间.
- * note 应用调用该函数接收数据,如果缓冲区无数据就等待.
- * param[in] id 指定的串口id.
- * param[in] pdata 需存储接收数据的缓冲区.
- * param[in] len 接收的数据长度.
- * param[in] timeout 设置为0表示一直等到接收到指定长度数据,设置为其他值表示等待指定超时时间(单位mS)
- * param[out] perro 错误码 0表示成功 -1表示参数错误 1表示超时
- * return int 返回实际读到的数据长度
- *****************************************************************************
- */
- unsigned int driver_uart_recv(HAL_UART_ID_e id, unsigned char *pdata, unsigned int len, unsigned int timeout, int *erro);
- /**
- *****************************************************************************
- * fn int driver_uart_send(HAL_UART_ID_e id, unsigned char *pdata, unsigned int len,unsigned int timeout,int *perro)
- * brief 串口发送指定长度数据,可以设置超时时间.
- * note 应用调用该函数发送数据,如果缓冲区满就等待.
- * param[in] id 指定的串口id.
- * param[in] pdata 需要发送的数据缓冲区.
- * param[in] len 需要发送的数据长度.
- * param[in] timeout 设置为0表示一直等到全部写入缓冲区,设置为其他值表示等待指定超时时间(单位mS)
- * param[out] perro 错误码 0表示成功 -1表示参数错误 1表示超时
- * return int 返回实际发送的数据
- *****************************************************************************
- */
- int driver_uart_send(HAL_UART_ID_e id, unsigned char *pdata, unsigned int len,unsigned int timeout,int *erro);
- /**
- *****************************************************************************
- * fn int driver_uart_haverxdata(HAL_UART_ID_e id)
- * brief 读串口是否曾经接收到过数据.
- * note 应用周期调用该函数用于判断是否点亮接收指示灯.读会清除状态.
- * param[in] id 指定的串口id.
- * retval 1 串口曾经有接收数据
- * retval 0 串口没有接收数据
- *****************************************************************************
- */
- int driver_uart_haverxdata(HAL_UART_ID_e id);
- /**
- *****************************************************************************
- * fn int driver_uart_havetxdata(HAL_UART_ID_e id)
- * brief 读串口是否曾经发送过数据.
- * note 应用周期调用该函数用于判断是否点亮发送指示灯.读会清除状态.
- * param[in] id 指定的串口id.
- * retval 1 串口曾经有发送数据
- * retval 0 串口没有发送数据
- *****************************************************************************
- */
- int driver_uart_havetxdata(HAL_UART_ID_e id);
- /**
- *****************************************************************************
- * fn int driver_uart_geterr(HAL_UART_ID_e id,unsigned int* err)
- * brief 读串口错误状态字.
- * note 应用调用该函数用于判断串口是否异常,如果err的低三个字节有任意个字节为FF则表示异常需要处理.
- * param[in] id 指定的串口id ref HAL_UART_ID_e .
- * param[out] err 存储错误字
- 0xxxxxxxFF表示校验错误
- 0xxxxxFFxx表示帧错误
- 0xxxFF00xx表示溢出错误
- * retval 0 总是返回0
- *****************************************************************************
- */
- int driver_uart_geterr(HAL_UART_ID_e id,unsigned int* err);
- /**
- * }
- */
- /**
- * }
- */
- /**
- * }
- */
- /**
- * }
- */
- #ifdef __cplusplus
- }
- #endif
- #endif
复制代码
测试上位机发送串口数据,板子收到后原样返回,测试是否完全一致。通过调整缓冲区大小和查询缓冲区的间隔,测试性能可以达到波特率对应的理想速度。 总结以上介绍了串口模块,实现了比较健壮好用的串口驱动,为后续的开发打下了基础。
|