精读OSAL --中断方式串行通信(_hal_uart_isr.c)
来源:互联网 发布:java 发邮件带附件 编辑:程序博客网 时间:2024/06/10 16:44
当在HAL里读完 _hal_uart_isr.c 就明白了TI的工程师写的发送接收算法.
static void HalUARTInitISR(void)
static void HalUARTOpenISR(halUARTCfg_t *config)
初始化和打开没什么好讲的,读文档就有了.
先在这里讲缓冲区算法
|-------------------|
head-->|-------------------|
|-------------------|
|-------------------|
|-------------------|
tail-->|-------------------|
|-------------------|
|-------------------|
|-------------------|
|-------------------|
|-------------------|
head和tail都是一个方向移动,当移到末位就回到开头位置.这个很重要..
读写函数不是真正的发送接改函数,他们只是负责将数填入上述的缓冲区,
或者从缓冲区中读出.
怎么操作呢? 读写函数只是将数填入或读出缓冲区,然后移动其中一个指针..
那么什么时候结束呢? 就是head==tail..
这里还有,另一个指针是在发送接收中断函数中移动.
这是这种你追我跑的方式发送接收.
这里开始读写函数
/***************************************************************************** * @fn HalUARTReadISR * * @brief Read a buffer from the UART * * @param buf - valid data buffer at least 'len' bytes in size * len - max length number of bytes to copy to 'buf' * * @return length of buffer that was read *****************************************************************************/static uint16 HalUARTReadISR(uint8 *buf, uint16 len){ uint16 cnt = 0; while ((isrCfg.rxHead != isrCfg.rxTail) && (cnt < len)) //这是读结束条件 { *buf++ = isrCfg.rxBuf[isrCfg.rxHead++]; if (isrCfg.rxHead >= HAL_UART_ISR_RX_MAX) { isrCfg.rxHead = 0; } cnt++; } return cnt;}/****************************************************************************** * @fn HalUARTWriteISR * * @brief Write a buffer to the UART. * * @param buf - pointer to the buffer that will be written, not freed * len - length of * * @return length of the buffer that was sent *****************************************************************************/static uint16 HalUARTWriteISR(uint8 *buf, uint16 len){ uint16 cnt; // Enforce all or none. if (HAL_UART_ISR_TX_AVAIL() < len) //判断长度是否大于当前有效长度 { return 0; } for (cnt = 0; cnt < len; cnt++) { isrCfg.txBuf[isrCfg.txTail] = *buf++; isrCfg.txMT = 0; if (isrCfg.txTail >= HAL_UART_ISR_TX_MAX-1) //缓冲区循环 { isrCfg.txTail = 0; } else { isrCfg.txTail++; } // Keep re-enabling ISR as it might be keeping up with this loop due to other ints. IEN2 |= UTXxIE; } return cnt;}
这里是中断服务程序:
/*************************************************************************************************** * @fn halUartRxIsr * * @brief UART Receive Interrupt * * @param None * * @return None ***************************************************************************************************/#if (HAL_UART_ISR == 1)HAL_ISR_FUNCTION( halUart0RxIsr, URX0_VECTOR )#elseHAL_ISR_FUNCTION( halUart1RxIsr, URX1_VECTOR )#endif{ HAL_ENTER_ISR(); uint8 tmp = UxDBUF; isrCfg.rxBuf[isrCfg.rxTail] = tmp; // Re-sync the shadow on any 1st byte received. if (isrCfg.rxHead == isrCfg.rxTail) { isrCfg.rxShdw = ST0; } if (++isrCfg.rxTail >= HAL_UART_ISR_RX_MAX) { isrCfg.rxTail = 0; } isrCfg.rxTick = HAL_UART_ISR_IDLE; HAL_EXIT_ISR();}/*************************************************************************************************** * @fn halUartTxIsr * * @brief UART Transmit Interrupt * * @param None * * @return None ***************************************************************************************************/#if (HAL_UART_ISR == 1)HAL_ISR_FUNCTION( halUart0TxIsr, UTX0_VECTOR )#elseHAL_ISR_FUNCTION( halUart1TxIsr, UTX1_VECTOR )#endif{ HAL_ENTER_ISR(); if (isrCfg.txHead == isrCfg.txTail) { IEN2 &= ~UTXxIE; isrCfg.txMT = 1; } else { UTXxIF = 0; UxDBUF = isrCfg.txBuf[isrCfg.txHead++]; if (isrCfg.txHead >= HAL_UART_ISR_TX_MAX) { isrCfg.txHead = 0; } } HAL_EXIT_ISR();}
都明白了吧?? 还有一个重要的东西:static void HalUARTPollISR(void)
这个函数是在OSAL每次循环中都调出一次,主要是设置事件,调用相应的回调函数.
static void HalUARTPollISR(void){ uint16 cnt = HAL_UART_ISR_RX_AVAIL(); uint8 evt = 0; if (isrCfg.rxTick) { // Use the LSB of the sleep timer (ST0 must be read first anyway). uint8 decr = ST0 - isrCfg.rxShdw; if (isrCfg.rxTick > decr) { isrCfg.rxTick -= decr; } else { isrCfg.rxTick = 0; } } isrCfg.rxShdw = ST0; if (cnt >= HAL_UART_ISR_RX_MAX-1) { evt = HAL_UART_RX_FULL; } else if (cnt >= HAL_UART_ISR_HIGH) { evt = HAL_UART_RX_ABOUT_FULL; } else if (cnt && !isrCfg.rxTick) { evt = HAL_UART_RX_TIMEOUT; } if (isrCfg.txMT) { isrCfg.txMT = 0; evt |= HAL_UART_TX_EMPTY; } if (evt && (isrCfg.uartCB != NULL)) { isrCfg.uartCB(HAL_UART_ISR-1, evt); }}
其它函数就不太重要了.
知道这些就很好理解了.
- 精读OSAL --中断方式串行通信(_hal_uart_isr.c)
- 精读OSAL --DMA方式串行通信(_hal_uart_dma.c)
- 精读OSAL --SPI方式串行通信(_hal_uart_spi.c)
- 精读OSAL --时钟及休眠(hal_sleep.c)
- 精读OSAL --按键的执行流程(hal_key.c onboard.c)
- 并行串行通信方式图解
- 串行通信程序(C#)
- 精读OSAL --回调函数的理解
- 精读OSAL --我的SPI驱动
- 单片机原理(3):中断、定时/计数、串行通信
- UART通信程序-中断方式
- 串行通信接口RS-232C
- STM32串行通讯采用中断方式发送,接收
- osal之添加中断向量
- 串行通信
- 串行通信
- 串行通信
- 串行通信
- 《我为单词狂》之节选band
- 读书笔记 -- 《时间触发嵌入式系统设计模式》 --- Part A_硬件基础
- MAC OS 常见五国错误解决办法
- js 显示当前时间
- c#创建xml文件并保存到指定位置
- 精读OSAL --中断方式串行通信(_hal_uart_isr.c)
- iOS开发那些事-如何编译iOS程序
- 远程服务器登录以及使用scp、sftp传输文件
- 计算机视觉相关的部分测试数据集和源码站点
- 什么是Linux内核模块
- Overlap IO与IOCP对比
- <<一分钟经理人>> 读后笔记
- 关于YII中的时间插件不能修改年份的解决方法
- Wince summary