|
串口收发数据
评估板自带了USB转串口,这个用起来方便多了,可以直接打印数据到电脑端。
下面上配置程序和收发处理。
用到资源UART2和TIMER6。准备之后连接modbus-RTU的所以占用一个定时器来判定接收报文结束
程序清单:
com_hal.h- #ifndef _COM_HAL_H_
- #define _COM_HAL_H_
- #include "mytype.h"
- #include "stdint.h"
- #ifdef _COM_HAL_MODULE_
- #define COM_EXT
- #else
- #define COM_EXT extern
- #endif
- #define COM USART2
- #define ComTIMER TIMER6
- typedef enum {
- COM_RX_IDLE, //!< Receiver is in idle state.
- COM_RX_RCV, //!< Frame is beeing received.
- COM_RX_RCVEND, //!< Port Receive complete ,3.5T timer
- COM_RX_TIMEOUT //!< Time out ,Send a command and no data return after 500ms( --> system timer)
- } ComRcvState_t;
- typedef enum {
- COM_TX_IDLE, /*!< Transmitter is in idle state. */
- COM_TX_XMIT /*!< Transmitter is in transfer state. */
- } ComSndState_t;
- typedef enum {
- COM_PAR_NONE, /*!< No parity. */
- COM_PAR_ODD, /*!< Odd parity. */
- COM_PAR_EVEN /*!< Even parity. */
- } ComParity_t;
- typedef union {
- uint8_t St;
- struct {
- uint8_t PortSt : 1;
- uint8_t Connect : 1;
- } bits;
- } COM_ST_Type;
- #define COM_BUFF_SIZE 1024
- COM_EXT uint8_t ComBuff[COM_BUFF_SIZE];
- COM_EXT COM_ST_Type ComSt;
- COM_EXT uint8_t *pComSndCur;
- COM_EXT uint16_t ComSndCnt;
- COM_EXT uint16_t ComRcvCnt;
- COM_EXT volatile uint8_t ComErrSt;
- COM_EXT volatile ComSndState_t ComSndSt;
- COM_EXT volatile ComRcvState_t ComRcvSt;
- void ComInit(uint32_t ulBaudRate, ComParity_t eParity);
- void ComParity(ComParity_t eParity);
- void ComStringSend(uint8_t * pData);
- void ComDataSend(uint8_t * pData, uint16_t Len);
- uint8_t ComStCheck(void); //端口空闲状态检查
- #undef COM_EXT
- #endif /* _COM_HAL_H_ */
复制代码 com_hal.c- /* ------------------------------------------------------------------------*
- *
- * ------------------------------------------------------------------------*/
- #include "osObjects.h"
- #define _COM_HAL_MODULE_
- #include "com_hal.h"
- #include "comtask.h"
- //RS485 Dir-Pin
- #define ComRxEnable()
- #define ComTxEnable()
- #define ComDE(x)
- static void ComEnable(uint8_t xRxEnable, uint8_t xTxEnable);
- void ComTimerEnable(void);
- void ComTimerDisable(void);
- /*****************************************************************************//*!
- * @brief UART2 TX interrupt routine.
- * @brief Uart interrupt.
- *
- * @param none
- *
- * @return none
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void USART2_IRQHandler() {
- uint32_t IntSt;
- uint8_t Data;
- IntSt = USART_STAT0(USART2);
- if (IntSt & USART_STAT0_RBNE) {
- ComTimerEnable();
- Data = USART_DATA(USART2);
- if (COM_RX_RCVEND == ComRcvSt)
- return;
- if (ComRcvCnt > (COM_BUFF_SIZE - 1))
- return; //指针越界检查
- ComRcvSt = COM_RX_RCV; //指示正在接收数据
- if ((IntSt & USART_STAT0_ORERR) != 0) { //溢出 //只读,由硬件管理
- }
- if ((IntSt & (USART_STAT0_FERR | USART_STAT0_PERR)) != 0) { //帧错误 //只读,由硬件管理
- return;
- }
- if (ComRcvCnt < COM_BUFF_SIZE)
- ComBuff[ComRcvCnt++] = Data;
- else {
- //receive overflow
- }
- } else if (IntSt & USART_STAT0_TBE) {
- if ((0 == ComSndCnt) && (IntSt & USART_STAT0_TC)) {
- ComSndSt = COM_TX_IDLE; //发送结束
- ComEnable(ENABLE, DISABLE);
- } else if (ComSndCnt) {
- USART_DATA(COM) = *(pComSndCur++);
- ComSndCnt--;
- if (0 == ComSndCnt) //写缓冲区结束
- {
- USART_CTL0(COM) &= ~(uint32_t) (USART_CTL0_TBEIE);
- USART_CTL0(COM) |= (uint32_t) (USART_CTL0_TCIE);
- }
- } else {
- }
- }
- }
- /*****************************************************************************//*!
- *
- * @brief com end timer.
- *
- * @param none
- *
- * @return none
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void TIMER6_IRQHandler() {
- //关闭定时器
- ComTimerDisable();
- //清除更新中断标志
- TIMER_INTF(ComTIMER) &= ~((uint32_t) TIMER_INTF_UPIF);
- //
- if (COM_RX_RCV == ComRcvSt) {
- //端口接收结束,告诉数据处理单元可以处理数据
- ComRcvSt = COM_RX_RCVEND;
- /* Set bit 0 and bit 4 in xEventGroup. */
- xSemaphoreGiveFromISR(xSemCom, NULL);
- }
- }
- /*****************************************************************************//*!
- *
- * @brief RTU timer enable.
- *
- * @param none
- *
- * @return none
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void ComTimerEnable(void) {
- TIMER_CNT(ComTIMER) = 0;
- TIMER_CTL0(ComTIMER) |= ((uint32_t) TIMER_CTL0_CEN);
- }
- /*****************************************************************************//*!
- *
- * @brief RTU timer disable.
- *
- * @param none
- *
- * @return none
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void ComTimerDisable(void) {
- //停止计数
- TIMER_CTL0(ComTIMER) &= ~((uint32_t) TIMER_CTL0_CEN);
- }
- /*****************************************************************************//*!
- *
- * @brief timer init.
- *
- * @param none
- *
- * @return TURE
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- uint8_t ComTimerInit(uint32_t ts50us) {
- uint32_t TimerClk;
- rcu_periph_clock_enable(RCU_TIMER6);
- rcu_periph_reset_enable(RCU_TIMER6RST);
- rcu_periph_reset_disable(RCU_TIMER6RST);
- TimerClk = rcu_clock_freq_get(CK_APB1);
- // 向上计数,仅溢出产生更新事件,单脉冲模式
- TIMER_CTL0(ComTIMER) = (uint32_t) (TIMER_CTL0_SPM | TIMER_CTL0_UPS);
- //预分频
- TIMER_PSC(ComTIMER) = TimerClk / 1000000 - 1;
- //装载值
- TIMER_CNT(ComTIMER) = 0;
- //周期
- TIMER_CAR(ComTIMER) = ts50us * 50 - 1; //auto reload value
- //禁止所有通道
- TIMER_CHCTL2(ComTIMER) = 0;
- //产生一次软件更新事件
- TIMER_SWEVG(ComTIMER) = TIMER_SWEVG_UPG; //update
- //清除更新中断标志
- TIMER_INTF(ComTIMER) &= ~((uint32_t) TIMER_INTF_UPIF);
- //更新事件产生中断
- TIMER_DMAINTEN(ComTIMER) = TIMER_DMAINTEN_UPIE;
- NVIC_SetPriority(TIMER6_IRQn, 0xFF);
- NVIC_ClearPendingIRQ(TIMER6_IRQn);
- NVIC_EnableIRQ(TIMER6_IRQn);
- return 1;
- }
- /*****************************************************************************//*!
- * @brief com modle init .
- *
- * @param none
- *
- * @return none
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void ComInit(uint32_t ulBaudRate, ComParity_t eParity) {
- uint32_t usTimerT35_50us;
- // Enable USART APB clock
- rcu_periph_clock_enable(RCU_USART2);
- rcu_periph_reset_enable(RCU_USART2RST);
- rcu_periph_reset_disable(RCU_USART2RST);
- gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_8 | GPIO_PIN_9);
- gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_8);
- gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_8);
- gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_9);
- gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
- usart_baudrate_set(COM, ulBaudRate);
- ComParity(eParity);
- //Timer init
- {
- if (ulBaudRate > 19200) {
- usTimerT35_50us = 35; /* 1800us. */
- } else {
- usTimerT35_50us = (7UL * 220000UL) / (2UL * ulBaudRate);
- }
- ComTimerInit(usTimerT35_50us);
- }
- ComSndSt = COM_TX_IDLE;
- ComRcvSt = COM_RX_IDLE;
- NVIC_SetPriority(USART2_IRQn, 0xFF);
- NVIC_ClearPendingIRQ(USART2_IRQn);
- NVIC_EnableIRQ(USART2_IRQn);
- ComEnable(ENABLE, DISABLE);
- }
- /*****************************************************************************//*!
- * @brief com parity set.
- *
- * @param none
- *
- * @return none
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void ComParity(ComParity_t eParity) {
- USART_CTL0(COM) &= ~((uint32_t) USART_CTL0_UEN);
- switch (eParity) {
- case COM_PAR_NONE:
- USART_CTL0(COM) &= ~((uint32_t) (USART_CTL0_PCEN | USART_CTL0_PM | USART_CTL0_WL));
- USART_CTL1(COM) &= ~((uint32_t) USART_CTL1_STB);
- USART_CTL1(COM) |= (uint32_t) BIT(13);
- break;
- case COM_PAR_ODD:
- USART_CTL0(COM) &= ~((uint32_t) (USART_CTL0_PCEN | USART_CTL0_PM | USART_CTL0_WL));
- USART_CTL1(COM) &= ~((uint32_t) USART_CTL1_STB);
- USART_CTL0(COM) |= (uint32_t) (USART_CTL0_PCEN | USART_CTL0_PM | USART_CTL0_WL);
- break;
- case COM_PAR_EVEN:
- USART_CTL0(COM) &= ~((uint32_t) (USART_CTL0_PCEN | USART_CTL0_PM | USART_CTL0_WL));
- USART_CTL1(COM) &= ~((uint32_t) USART_CTL1_STB);
- USART_CTL0(COM) |= (uint32_t) (USART_CTL0_PCEN | USART_CTL0_WL);
- break;
- default:
- break;
- }
- USART_CTL0(COM) |= ((uint32_t) USART_CTL0_UEN);
- }
- /*****************************************************************************//*!
- *
- * @brief Uart En or Dis.
- *
- * @param none
- *
- * @return none
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- static void ComEnable(uint8_t xRxEnable, uint8_t xTxEnable) {
- volatile uint8_t u8Temp;
- volatile uint32_t u32Temp;
- if (xRxEnable) {
- USART_CTL0(COM) &= ~((uint32_t) USART_CTL0_TCIE);
- USART_CTL0(COM) &= ~((uint32_t) USART_CTL0_TBEIE);
- ComRxEnable();
- USART_CTL0(COM) &= ~((uint32_t) USART_CTL0_TEN);
- USART_CTL0(COM) |= (uint32_t) USART_CTL0_REN;
- u8Temp = USART_DATA(COM);
- u32Temp = USART_STAT0(COM);
- while ((USART_STAT0(COM) & (USART_STAT0_RBNE | USART_STAT0_ORERR)) != 0) {
- u32Temp = USART_STAT0(COM);
- u8Temp = USART_DATA(COM);
- }
- USART_CTL0(COM) |= USART_CTL0_RBNEIE;
- } else if (xTxEnable) {
- USART_CTL0(COM) &= ~((uint32_t) USART_CTL0_RBNEIE);
- USART_CTL0(COM) &= ~((uint32_t) USART_CTL0_REN);
- USART_CTL0(COM) |= (uint32_t) USART_CTL0_TEN;
- ComTxEnable();
- ComSndCnt--;
- USART_DATA(COM) = *(pComSndCur++);
- USART_CTL0(COM) |= (uint32_t) (USART_CTL0_TBEIE);
- } else {
- }
- }
- /*****************************************************************************//*!
- *
- * @brief Send a string.
- *
- * @param none
- *
- * @return none
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void ComStringSend(uint8_t * pData) {
- if (COM_TX_IDLE == ComSndSt) {
- pComSndCur = pData;
- ComSndCnt = 0;
- while (*pData++)
- ComSndCnt++;
- ComSndSt = COM_TX_XMIT;
- ComEnable(DISABLE, ENABLE);
- } else {
- }
- }
- /*****************************************************************************//*!
- *
- * @brief Send data.
- *
- * @param none
- *
- * @return none
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void ComDataSend(uint8_t * pData, uint16_t Len) {
- if (ComStCheck()) {
- ComSndCnt = Len;
- ComSndSt = COM_TX_XMIT;
- pComSndCur = pData;
- ComEnable(DISABLE, ENABLE);
- } else {
- }
- }
- /*****************************************************************************//*!
- *
- * @brief Port state check.
- *
- * @param none
- *
- * @return none
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- uint8_t ComStCheck(void) {
- if (ComSndSt != COM_TX_IDLE)
- return 0;
- if (ComRcvSt != COM_RX_IDLE)
- return 0;
- return 1;
- }
复制代码 cominfo.h- #ifndef _COM_INFO_H_
- #define _COM_INFO_H_
- #include "stdint.h"
- extern uint8_t const ComInfo[][64];
- #define COM_INFO_TEST 0
- #define COM_INFO_VER (COM_INFO_TEST + 1)
- #define COM_INFO_NOCMD (COM_INFO_VER + 1)
- #endif /* _COM_INFO_H_ */
复制代码 cominfo.c- /* ------------------------------------------------------------------------*
- *
- * ------------------------------------------------------------------------*/
- #include "stdint.h"
- uint8_t const ComInfo[][64] =
- {
- "Communicate OK !\r\n\0",
- "System version : 0.01.\r\n\0",
- "No Command Received.\r\n\0"
- };
复制代码 comtask.h- ifndef _COM_TASK_H_
- #define _COM_TASK_H_
- #include "mytype.h"
- #include "stdint.h"
- #define COM_EVENT_RCVEND (0x01UL)
- #define COM_EVENT_TIMOUT (0x02UL)
- #define COMDLYTIMEOUT 3000
- #define CMD_START (':')
- #endif /* _COM_TASK_H_ */
复制代码 comtask.c工程使用了freertos系统,串口收发需要创建一个任务和用于同步的信号量
创建任务
if(pdPASS != xTaskCreate( ComTask, "Com", COM_TASK_STACK_SIZE, NULL, COM_TASK_PRIORITY, NULL )) while(1);
创建信号量
vSemaphoreCreateBinary( xSemCom );
if(NULL == xSemCom) while(1);
|
|