- static gpio_init_cfg_type gpio_cfg[] =
- {
- //UART1
- {GPIOA, GPIO_Mode_AF_PP, GPIO_MaxSpeed_50MHz, 0, GPIO_Pins_9}, //u1-TX
- {GPIOA, GPIO_Mode_IN_PU, GPIO_MaxSpeed_50MHz, 0, GPIO_Pins_10}, //u1-RX
- //ADC
- {GPIOA, GPIO_Mode_IN_ANALOG, GPIO_MaxSpeed_50MHz, 0, GPIO_Pins_0}, //ADC
- //LED
- {GPIOD, GPIO_Mode_OUT_PP, GPIO_MaxSpeed_50MHz, 1, GPIO_Pins_13 | GPIO_Pins_14 | GPIO_Pins_15}, //LED
- {GPIOD, GPIO_Mode_AF_PP, GPIO_MaxSpeed_50MHz, 0, GPIO_Pins_15}, //LED-PWM
- //UART8
- {GPIOE, GPIO_Mode_AF_PP, GPIO_MaxSpeed_50MHz, 0, GPIO_Pins_1}, //u8-TX
- {GPIOE, GPIO_Mode_IN_PU, GPIO_MaxSpeed_50MHz, 0, GPIO_Pins_0}, //u8-RX
- //UART6
- {GPIOC, GPIO_Mode_AF_PP, GPIO_MaxSpeed_50MHz, 0, GPIO_Pins_6}, //u6-TX
- {GPIOC, GPIO_Mode_IN_PU, GPIO_MaxSpeed_50MHz, 0, GPIO_Pins_7}, //u6-RX
- //SPI1
- {GPIOA, GPIO_Mode_AF_PP, GPIO_MaxSpeed_50MHz, 0, GPIO_Pins_5 | GPIO_Pins_7}, //SPI1-SCK MOSI
- {GPIOA, GPIO_Mode_IN_PU, GPIO_MaxSpeed_50MHz, 0, GPIO_Pins_6}, //SPI1-MISO
- {GPIOA, GPIO_Mode_OUT_PP, GPIO_MaxSpeed_50MHz, 1, GPIO_Pins_15}, //SPI1-SS
- };
- for(index=0; index < sizeof(gpio_cfg)/sizeof(gpio_init_cfg_type);index++)
- {
- GPIO_InitType GPIO_InitStructure;
-
- GPIO_InitStructure.GPIO_Mode = gpio_cfg[index].mode;
- GPIO_InitStructure.GPIO_MaxSpeed = gpio_cfg[index].speed;
- GPIO_InitStructure.GPIO_Pins = gpio_cfg[index].pin;
- GPIO_Init(gpio_cfg[index].port, &GPIO_InitStructure);
-
- if((gpio_cfg[index].mode == GPIO_Mode_OUT_OD) || (gpio_cfg[index].mode == GPIO_Mode_OUT_PP))
- {
- if(gpio_cfg[index].val_init)
- {
- GPIO_SetBits(gpio_cfg[index].port, gpio_cfg[index].pin);
- }
- else
- {
- GPIO_ResetBits(gpio_cfg[index].port, gpio_cfg[index].pin);
- }
- }
- }
测试开通两个通道,一路主机-UART6,一路从机-UART8。
协议解析用现成的库,只需要编写底层数据收发文件。
- #include "sys_ext.h"
- #include "os_obj.h"
- #include "mbapp.h"
- #define mbPORT USART6
- #define mbURT_IRQn USART6_IRQn
- #define mbISR USART6_IRQHandler
- #define RCU_USART RCC_APB2PERIPH_USART6
- #define RCU_USARTRST RCC_APB2PERIPH_USART6
- #define mbObj mb.obj06
- #define mbCmdBuff mb.CmdBuff06
- static volatile uint8_t alDir;
- //RS485 Dir-Pin
- #define mbRxEnable()
- #define mbTxEnable()
- static void mbswTimerEnable(void);
- static void mbEnable(uint8_t xRxEnable, uint8_t xTxEnable);
- static void mbDataSend(void);
- #include "mb_fun.h"
- /*****************************************************************************//*!
- *
- * [url=home.php?mod=space&uid=247401]@brief[/url] port.
- * [url=home.php?mod=space&uid=72445]@[/url] Pass/ Fail criteria: none
- *****************************************************************************/
- static void mb_port_pin_cfg(void)
- {
- intx_disable();
- RCC_APB2PeriphClockCmd(RCU_USART, ENABLE);
- RCC_APB2PeriphResetCmd(RCU_USARTRST, ENABLE);
- RCC_APB2PeriphResetCmd(RCU_USARTRST, DISABLE);
- intx_enable();
- }
- /*****************************************************************************//*!
- *
- * [url=home.php?mod=space&uid=247401]@brief[/url] RTU timer enable.
- * [url=home.php?mod=space&uid=72445]@[/url] Pass/ Fail criteria: none
- *****************************************************************************/
- __STATIC_INLINE void mbswTimerEnable(void)
- {
- mbObj.bRtuTimerOn = 1;
- mbObj.RtuTimerCnt = 0;
- }
- /*****************************************************************************//*!
- * @brief UART0 RX interrupt routine.
- * @brief Uart interrupt.
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void mbISR()
- {
- volatile uint32_t IntSt;
- volatile uint8_t Data;
- mbObj.TimeOutCnt = 0;
- IntSt = mbPORT->STS;
- if (IntSt & USART_STS_RDNE)
- {
- Data = mbPORT->DT;
- mbObj.RunSt.bits.PortSt = 1;
- if (MB_RX_RCVEND == mbObj.RcvSt)
- return;
- if (mbObj.SndSt != MB_TX_IDLE)
- return;
- mbObj.RcvSt = MB_RX_RCV; //指示正在接收数据
- mbswTimerEnable();
- if (mbObj.RcvCnt >= MB_BUFF_SIZE)
- return; //指针越界检查
- if ((IntSt & (USART_STS_PERR | USART_STS_FERR | USART_STS_ORERR)) != 0) //帧错误 //只读,由硬件管理
- {
- if (mbObj.RcvCnt >= 1)
- {
- mbObj.ErrSt.bits.ErrHal = 1;
- }
- }
- mbObj.AduBuff[mbObj.RcvCnt++] = Data;
- }
- else if ((mbObj.SndSize <= mbObj.SndCnt) && (IntSt & USART_STS_TRAC))
- {
- mbObj.SndSt = MB_TX_IDLE; //发送结束
- if (mbObj.RunSt.bits.MasterMode) //主机进入接收等待状态
- {
- mbObj.RcvSt = MB_RX_WAIT;
- }
- mbEnable(ENABLE, DISABLE);
- }
- else if (IntSt & USART_STS_TDE)
- {
- if (mbObj.SndSize > mbObj.SndCnt)
- {
- mbPORT->DT = mbObj.AduBuff[mbObj.SndCnt++];
- }
- else //写缓冲区结束
- {
- mbPORT->CTRL1 &= ~((uint32_t)(USART_CTRL1_TDEIEN));
- mbPORT->CTRL1 |= (uint32_t)(USART_CTRL1_TRACIEN);
- }
- }
- else
- {
- }
-
- cpu_data_sync();
- }
- /*****************************************************************************//*!
- *
- * @brief mb object init.
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- static void mbObjInit(mb_mode_type mbMode)
- {
- mb_obj_init(&mbObj);
- mbObj.AduSend = &mbDataSend;
- mbObj.RunSt.bits.RTUMode = 1;
- mbObj.Fun.Slave.RegCoilsCB = &eMBRegCoilsCB;
- mbObj.Fun.Slave.RegDiscreteCB = &eMBRegDiscreteCB;
- mbObj.Fun.Slave.RegHoldingCB = &eMBRegHoldingCB;
- mbObj.Fun.Slave.RegInputCB = &eMBRegInputCB;
- mmb_cmd_buff_init(&mbObj, mbCmdBuff, 32, 16);
- mbObj.Fun.Master.ErrCnt = 0;
- mbObj.api = &mb_fun;
-
- //SLAVE FUNCTION INIT
- if (MB_RTU_SLAVE == mbMode)
- {
- }
- else
- {
- //MASER FUNCTION INIT
- mbObj.RunSt.bits.MasterMode = 1;
- }
- }
- /*****************************************************************************//*!
- * @brief com modle init .
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void mb06_Init(mb_mode_type mbMode, uint32_t ulBaudRate, mb_parity_type eParity)
- {
- uint32_t usTimerT35_50us;
- USART_InitType cfg;
- mb_port_pin_cfg();
- mbObjInit(mbMode);
- cfg.USART_BaudRate = ulBaudRate;
- cfg.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
- cfg.USART_HardwareFlowControl = 0;
- if (MB_PAR_NONE == eParity)
- {
- cfg.USART_Parity = USART_Parity_No;
- cfg.USART_StopBits = USART_StopBits_2;
- cfg.USART_WordLength = USART_WordLength_8b;
- }
- else if (MB_PAR_NONE_1S == eParity)
- {
- cfg.USART_Parity = USART_Parity_No;
- cfg.USART_StopBits = USART_StopBits_1;
- cfg.USART_WordLength = USART_WordLength_8b;
- }
- else if (MB_PAR_ODD == eParity)
- {
- cfg.USART_Parity = USART_Parity_Odd;
- cfg.USART_StopBits = USART_StopBits_1;
- cfg.USART_WordLength = USART_WordLength_9b;
- }
- else
- {
- cfg.USART_Parity = USART_Parity_Even;
- cfg.USART_StopBits = USART_StopBits_1;
- cfg.USART_WordLength = USART_WordLength_9b;
- }
- if (ulBaudRate > 19200)
- {
- usTimerT35_50us = 35; /* 1800us. */
- mbObj.RtuTimerSv = 3;
- }
- else
- {
- usTimerT35_50us = (7UL * 220000UL) / (2UL * ulBaudRate);
- mbObj.RtuTimerSv = usTimerT35_50us / 20 + 2;
- }
- USART_Init(mbPORT, &cfg);
- USART_Cmd(mbPORT, ENABLE);
- nvic_irq_set(mbURT_IRQn, 0x0F, 1);
- mbEnable(ENABLE, DISABLE);
- }
- /*****************************************************************************//*!
- *
- * @brief Uart En or Dis.
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- static void mbEnable(uint8_t xRxEnable, uint8_t xTxEnable)
- {
- volatile uint8_t u8Temp;
- if (xRxEnable)
- {
- mbRxEnable();
- mbPORT->CTRL1 &= ~((uint32_t)USART_CTRL1_TDEIEN | USART_CTRL1_TRACIEN);
- mbPORT->CTRL1 |= (uint32_t)USART_CTRL1_REN | USART_CTRL1_UEN;
- u8Temp = mbPORT->DT;
- while ((mbPORT->STS & (USART_STS_RDNE | USART_STS_ORERR)) != 0)
- {
- u8Temp = mbPORT->DT;
- __DSB();
- }
- mbPORT->CTRL1 |= USART_CTRL1_RDNEIEN;
- }
- else if (xTxEnable)
- {
- mbPORT->CTRL1 &= ~((uint32_t)USART_CTRL1_RDNEIEN | USART_CTRL1_REN);
- mbPORT->CTRL1 |= (uint32_t)USART_CTRL1_TEN | USART_CTRL1_UEN;
- mbTxEnable();
- mbPORT->DT = mbObj.AduBuff[mbObj.SndCnt++];
- mbPORT->CTRL1 |= (uint32_t)(USART_CTRL1_TDEIEN);
- }
- else
- {
- }
- }
- /*****************************************************************************//*!
- *
- * @brief Send data.
- *
- * @ Pass/ Fail criteria: none
- *****************************************************************************/
- void mbDataSend(void)
- {
- mbEnable(DISABLE, ENABLE);
- }
RTU定时使用软件定时器,这样可以避免硬件资源不足,方便添加多通道。
- /**
- * @brief app timer isr
- * @param None
- * @retval None
- */
- void AdcInsertedHandle(void);
- void app_timer_isr(void)
- {
- APP_TIM->STS = 0;
-
- sys_st.u_tick++;
- AdcInsertedHandle();
-
- if(com.obj01.fun)
- com.obj01.fun->timer_handle();
-
- if(mb.obj08.api)
- mb.obj08.api->rtu_timer_run();
-
- if(mb.obj06.api)
- mb.obj06.api->rtu_timer_run();
-
- cpu_data_sync();
- }
modbus任务配置两条静态处理命令,分别为读取8字和写8字。
根据测试平均每秒执行指令30+次。
-
- void modbus_task (void const *argument)
- {
- mb_obj_init(&mb.obj08);
- //从机配置
- mb08_Init(MB_RTU_SLAVE, mb_baud_tab[MB_BAUD_19200], MB_PAR_NONE);
- mb.obj08.SlaveId = 1;
- mb.obj08.os_event_send = mb_os_send;
- mb.obj08.os_rtu_end_event = 1;
- mb.obj08.os_timeout_event = 2;
-
- mb_obj_init(&mb.obj06);
- //主机配置
- mb06_Init(MB_RTU_MASTER, mb_baud_tab[MB_BAUD_19200], MB_PAR_NONE);
- mb.obj06.SlaveId = 1;
- mb.obj06.RtuRcvendDelaySet = 3;
- mb.obj06.rcv_end_handle_comp = rcv_end_handle_comp;
- mb.obj06.os_event_send = mb_os_send;
- mb.obj06.os_rtu_end_event = 1;
- mb.obj06.os_timeout_event = 2;
-
- mb.obj06.api->stc_cmd_req(0, 1, FUN_CODE_WRITE_MULTIPLE_REG, mb_tst.pv_w, 0, 8, 0);
- mb.obj06.api->stc_cmd_req(0, 1, FUN_CODE_READ_REG, mb_tst.pv_r, 0, 8, 0);
-
- //任务处理
- for(;;)
- {
- osSignalWait(0, ms_ticks(100));
-
- mb_poll(&mb.obj08);
-
- mb_poll(&mb.obj06);
- }
- }
附上测试工程,IAR8.40版以上可用
software.rar
(9.11 MB, 下载次数: 261)