├── README.md ├── mb_crc.c ├── mb_crc.h ├── mb_hook.c ├── mb_hook.h ├── mb_host.c ├── mb_host.h ├── mb_include.h ├── mb_port.c └── mb_port.h /README.md: -------------------------------------------------------------------------------- 1 | # modbus-host 2 | modbus主机代码,可以用在各种MCU平台 3 | -------------------------------------------------------------------------------- /mb_crc.c: -------------------------------------------------------------------------------- 1 | #include "mb_include.h" 2 | 3 | static const uint8_t aucCRCHi[] = { 4 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 5 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 6 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 7 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 8 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 9 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 10 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 11 | 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 12 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 13 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 14 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 15 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 16 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 17 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 18 | 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 19 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 20 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 21 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 22 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 23 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 24 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 25 | 0x00, 0xC1, 0x81, 0x40 26 | }; 27 | 28 | static const uint8_t aucCRCLo[] = { 29 | 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 30 | 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 31 | 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 32 | 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 33 | 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 34 | 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 35 | 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 36 | 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 37 | 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 38 | 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 39 | 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 40 | 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 41 | 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 42 | 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 43 | 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 44 | 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 45 | 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 46 | 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 47 | 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 48 | 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 49 | 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 50 | 0x41, 0x81, 0x80, 0x40 51 | }; 52 | 53 | uint16_t mb_crc16( uint8_t * pFrame, uint16_t len ) 54 | { 55 | uint8_t ucCRCHi = 0xFF; 56 | uint8_t ucCRCLo = 0xFF; 57 | int iIndex; 58 | 59 | while( len-- ) 60 | { 61 | iIndex = ucCRCLo ^ *( pFrame++ ); 62 | ucCRCLo = ( uint8_t )( ucCRCHi ^ aucCRCHi[iIndex] ); 63 | ucCRCHi = aucCRCLo[iIndex]; 64 | } 65 | return ( uint16_t )( ucCRCHi << 8 | ucCRCLo ); 66 | } 67 | -------------------------------------------------------------------------------- /mb_crc.h: -------------------------------------------------------------------------------- 1 | #ifndef __MB_CRC16_H 2 | #define __MB_CRC16_H 3 | 4 | uint16_t mb_crc16( uint8_t * pFrame, uint16_t len ); 5 | 6 | #endif 7 | 8 | -------------------------------------------------------------------------------- /mb_hook.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file mb_hook.c 4 | * @author Derrick Wang 5 | * @brief modebus回调函数接口 6 | ****************************************************************************** 7 | * @note 8 | * 针对modbus的回调处理,请再该文件中添加 9 | ****************************************************************************** 10 | */ 11 | 12 | #include "mb_include.h" 13 | 14 | void mbh_hook_rec01(uint8_t add,uint8_t *data,uint8_t datalen) 15 | { 16 | 17 | } 18 | void mbh_hook_rec02(uint8_t add,uint8_t *data,uint8_t datalen) 19 | { 20 | 21 | } 22 | void mbh_hook_rec03(uint8_t add,uint8_t *data,uint8_t datalen) 23 | { 24 | 25 | } 26 | void mbh_hook_rec04(uint8_t add,uint8_t *data,uint8_t datalen) 27 | { 28 | 29 | } 30 | void mbh_hook_rec05(uint8_t add,uint8_t *data,uint8_t datalen) 31 | { 32 | 33 | } 34 | void mbh_hook_rec06(uint8_t add,uint8_t *data,uint8_t datalen) 35 | { 36 | 37 | } 38 | void mbh_hook_rec15(uint8_t add,uint8_t *data,uint8_t datalen) 39 | { 40 | 41 | } 42 | void mbh_hook_rec16(uint8_t add,uint8_t *data,uint8_t datalen) 43 | { 44 | 45 | } 46 | 47 | 48 | void mbh_hook_timesErr(uint8_t add,uint8_t cmd) 49 | { 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /mb_hook.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file mb_hook.c 4 | * @author Derrick Wang 5 | * @brief modebus回调函数头文件 6 | ****************************************************************************** 7 | * @note 8 | * 9 | ****************************************************************************** 10 | */ 11 | 12 | #ifndef __MB_HOOK_H 13 | #define __MB_HOOK_H 14 | 15 | /** 16 | * @brief MODBUS主机模式下接收到从机回复不同功能码的回调处理 17 | * @param add:从机的地址 18 | * @param data:接收到的从机发来的数据指针 19 | * @param datalen:接收到的从机发来的数据长度 20 | * @return NONE 21 | * @note rec01\02\03……等数字代表功能码 22 | */ 23 | void mbh_hook_rec01(uint8_t add,uint8_t *data,uint8_t datalen); 24 | void mbh_hook_rec02(uint8_t add,uint8_t *data,uint8_t datalen); 25 | void mbh_hook_rec03(uint8_t add,uint8_t *data,uint8_t datalen); 26 | void mbh_hook_rec04(uint8_t add,uint8_t *data,uint8_t datalen); 27 | void mbh_hook_rec05(uint8_t add,uint8_t *data,uint8_t datalen); 28 | void mbh_hook_rec06(uint8_t add,uint8_t *data,uint8_t datalen); 29 | void mbh_hook_rec15(uint8_t add,uint8_t *data,uint8_t datalen); 30 | void mbh_hook_rec16(uint8_t add,uint8_t *data,uint8_t datalen); 31 | /** 32 | * @brief MODBUS主机读写从机超过最大错误次数回调 33 | * @param add:从机的地址 34 | * @param cmd:功能码 35 | * @return NONE 36 | * @note 37 | */ 38 | void mbh_hook_timesErr(uint8_t add,uint8_t cmd); 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /mb_host.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file mb_host.c 4 | * @author Derrick Wang 5 | * @brief modebus主机实现代码 6 | ****************************************************************************** 7 | * @note 8 | * 该文件无需修改 9 | ****************************************************************************** 10 | */ 11 | 12 | #include "mb_include.h" 13 | #include "string.h" 14 | 15 | struct 16 | { 17 | uint8_t state; //modbus host状态 18 | uint8_t errTimes; //失败次数计数 19 | uint8_t txLen; //需要发送的帧长度 20 | uint8_t txCounter; //已发送bytes计数 21 | uint8_t txBuf[MBH_RTU_MAX_SIZE]; //发送缓冲区 22 | uint8_t rxCounter; //接收计数 23 | uint8_t rxBuf[MBH_RTU_MAX_SIZE]; //接收缓冲区 24 | uint8_t rxTimeOut; //接收时的超时计数 25 | 26 | }mbHost; 27 | 28 | 29 | //modbus初始化 30 | void mbh_init(uint32_t baud,uint8_t parity) 31 | { 32 | mb_port_uartInit(baud,parity); 33 | mb_port_timerInit(baud); 34 | } 35 | uint8_t mbh_getState() 36 | { 37 | return mbHost.state; 38 | } 39 | 40 | //发送一帧命令 41 | int8_t mbh_send(uint8_t add,uint8_t cmd,uint8_t *data,uint8_t data_len) 42 | { 43 | uint16_t crc; 44 | if(mbHost.state!=MBH_STATE_IDLE)return -1; //busy state 45 | 46 | mbHost.txCounter=0; 47 | mbHost.rxCounter=0; 48 | mbHost.txBuf[0]=add; 49 | mbHost.txBuf[1]=cmd; 50 | memcpy((mbHost.txBuf+2),data,data_len); 51 | mbHost.txLen=data_len+2; //data(n)+add(1)+cmd(1) 52 | crc=mb_crc16(mbHost.txBuf,mbHost.txLen); 53 | mbHost.txBuf[mbHost.txLen++]=(uint8_t)(crc&0xff); 54 | mbHost.txBuf[mbHost.txLen++]=(uint8_t)(crc>>8); 55 | 56 | mbHost.state=MBH_STATE_TX; 57 | mb_port_uartEnable(1,0); //enable tx,disable rx 58 | /*当打开TXE中断以后,立马就会触发一次,所以这里不用先发送一个byte*/ 59 | //mb_port_putchar(mbHost.txBuf[mbHost.txCounter++]); //send first char,then enter tx isr 60 | return 0; 61 | } 62 | //接收正确,进行解析处理 63 | void mbh_exec(uint8_t *pframe,uint8_t len) 64 | { 65 | uint8_t datalen=len-2; 66 | switch(pframe[1])//cmd 67 | { 68 | case 1: 69 | mbh_hook_rec01(pframe[0],(pframe+2),datalen); 70 | break; 71 | case 2: 72 | mbh_hook_rec02(pframe[0],(pframe+2),datalen); 73 | break; 74 | case 3: 75 | mbh_hook_rec03(pframe[0],(pframe+2),datalen); 76 | break; 77 | case 4: 78 | mbh_hook_rec04(pframe[0],(pframe+2),datalen); 79 | break; 80 | case 5: 81 | mbh_hook_rec05(pframe[0],(pframe+2),datalen); 82 | break; 83 | case 6: 84 | mbh_hook_rec06(pframe[0],(pframe+2),datalen); 85 | break; 86 | case 15: 87 | mbh_hook_rec15(pframe[0],(pframe+2),datalen); 88 | break; 89 | case 16: 90 | mbh_hook_rec16(pframe[0],(pframe+2),datalen); 91 | break; 92 | } 93 | } 94 | void mbh_poll() 95 | { 96 | switch(mbHost.state) 97 | { 98 | /*接收完一帧数据,开始进行校验*/ 99 | case MBH_STATE_RX_CHECK: //接收完成,对一帧数据进行检查 100 | if((mbHost.rxCounter>=MBH_RTU_MIN_SIZE)&&(mb_crc16(mbHost.rxBuf,mbHost.rxCounter)==0)) //接收的一帧数据正确 101 | { 102 | if((mbHost.txBuf[0]==mbHost.rxBuf[0])&&(mbHost.txBuf[1]==mbHost.rxBuf[1])) //发送帧数据和接收到的帧数据地址和功能码一样 103 | { 104 | mbHost.state=MBH_STATE_EXEC; 105 | } 106 | else mbHost.state=MBH_STATE_REC_ERR; 107 | 108 | } 109 | else mbHost.state=MBH_STATE_REC_ERR; 110 | break; 111 | /*接收一帧数据出错*/ 112 | case MBH_STATE_REC_ERR: 113 | mbHost.errTimes++; 114 | if(mbHost.errTimes>=MBH_ERR_MAX_TIMES) 115 | { 116 | mbHost.state=MBH_STATE_TIMES_ERR; 117 | } 118 | else //重新再启动一次传输 119 | { 120 | mbHost.txCounter=0; 121 | mbHost.rxCounter=0; 122 | mbHost.state=MBH_STATE_TX; 123 | mb_port_uartEnable(1,0); //enable tx,disable rx 124 | } 125 | break; 126 | /*超过最大错误传输次数*/ 127 | case MBH_STATE_TIMES_ERR: 128 | mbh_hook_timesErr(mbHost.txBuf[0],mbHost.txBuf[1]); 129 | mbHost.txCounter=0; 130 | mbHost.rxCounter=0; 131 | break; 132 | /*确定接收正确执行回调*/ 133 | case MBH_STATE_EXEC: //主机发送接收完成,执行回调 134 | mbh_exec(mbHost.rxBuf,mbHost.rxCounter); 135 | mbHost.state=MBH_STATE_IDLE; 136 | break; 137 | 138 | } 139 | } 140 | 141 | 142 | void mbh_timer3T5Isr() 143 | { 144 | switch(mbHost.state) 145 | { 146 | /*发送完但没有接收到数据*/ 147 | case MBH_STATE_TX_END: 148 | mbHost.rxTimeOut++; 149 | if(mbHost.rxTimeOut>=MBH_REC_TIMEOUT) //接收超时 150 | { 151 | mbHost.rxTimeOut=0; 152 | mbHost.state=MBH_STATE_REC_ERR; 153 | mb_port_timerDisable(); //关闭定时器 154 | mb_port_uartEnable(0,0); //串口tx、rx都关闭 155 | } 156 | break; 157 | case MBH_STATE_RX: //3.5T到,接收一帧完成 158 | mbHost.state=MBH_STATE_RX_CHECK; 159 | mb_port_timerDisable(); //关闭定时器 160 | mb_port_uartEnable(0,0); //串口tx、rx都关闭 161 | break; 162 | } 163 | 164 | } 165 | void mbh_uartRxIsr() 166 | { 167 | uint8_t ch; 168 | mb_port_getchar(&ch); 169 | switch(mbHost.state) 170 | { 171 | case MBH_STATE_TX_END: 172 | mbHost.rxCounter=0; 173 | mbHost.rxBuf[mbHost.rxCounter++]=ch; 174 | mbHost.state=MBH_STATE_RX; 175 | mb_port_timerEnable(); 176 | break; 177 | case MBH_STATE_RX: 178 | if(mbHost.rxCounterDR = ch; //直接操作寄存器比HAL封装的更高效 72 | } 73 | 74 | void mb_port_getchar(uint8_t *ch) 75 | { 76 | *ch= (uint8_t)(huart1.Instance->DR & (uint8_t)0x00FF); 77 | } 78 | 79 | void mb_port_timerInit(uint32_t baud) 80 | { 81 | /*定时器部分初始化*/ 82 | htim3.Instance = TIM3; 83 | htim3.Init.Prescaler = 71; 84 | htim3.Init.CounterMode = TIM_COUNTERMODE_UP; 85 | if(baud>19200) //波特率大于19200固定使用1800作为3.5T 86 | { 87 | htim3.Init.Period = 1800; 88 | } 89 | else //其他波特率的需要根据计算 90 | { 91 | /* us=1s/(baud/11)*1000000*3.5 92 | * =(11*1000000*3.5)/baud 93 | * =38500000/baud 94 | */ 95 | htim3.Init.Period = (uint32_t)38500000/baud; 96 | 97 | } 98 | htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; 99 | htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; 100 | if (HAL_TIM_Base_Init(&htim3) != HAL_OK) 101 | { 102 | Error_Handler(); 103 | } 104 | } 105 | 106 | void mb_port_timerEnable() 107 | { 108 | __HAL_TIM_DISABLE(&htim3); 109 | __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_UPDATE); //清除中断位 110 | __HAL_TIM_ENABLE_IT(&htim3,TIM_IT_UPDATE); //使能中断位 111 | __HAL_TIM_SET_COUNTER(&htim3,0); //设置定时器计数为0 112 | __HAL_TIM_ENABLE(&htim3); //使能定时器 113 | } 114 | 115 | void mb_port_timerDisable() 116 | { 117 | __HAL_TIM_DISABLE(&htim3); 118 | __HAL_TIM_SET_COUNTER(&htim3,0); 119 | __HAL_TIM_DISABLE_IT(&htim3,TIM_IT_UPDATE); 120 | __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_UPDATE); 121 | } 122 | 123 | //串口中断服务函数 124 | void USART1_IRQHandler() 125 | { 126 | HAL_NVIC_ClearPendingIRQ(USART1_IRQn); 127 | if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE)!=RESET)) 128 | { 129 | __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_RXNE); 130 | mbh_uartRxIsr(); 131 | } 132 | if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_TXE)!=RESET)) 133 | { 134 | __HAL_UART_CLEAR_FLAG(&huart1,UART_FLAG_TXE); 135 | mbh_uartTxIsr(); 136 | } 137 | } 138 | 139 | //定时器中断服务函数 140 | void TIM3_IRQHandler() 141 | { 142 | __HAL_TIM_CLEAR_IT(&htim3,TIM_IT_UPDATE); 143 | mbh_timer3T5Isr(); 144 | } 145 | 146 | -------------------------------------------------------------------------------- /mb_port.h: -------------------------------------------------------------------------------- 1 | #ifndef __MB_PORT_H 2 | #define __MB_PORT_H 3 | 4 | /** 5 | ****************************************************************************** 6 | * @file mb_port.h 7 | * @author Derrick Wang 8 | * @brief modebus移植接口头文件 9 | ****************************************************************************** 10 | * @note 11 | * 该文件为modbus移植接口的实现,根据不同的MCU平台进行移植 12 | ****************************************************************************** 13 | */ 14 | 15 | 16 | typedef enum 17 | { 18 | MB_PARITY_NONE=0X00, //无奇偶校验,两个停止位 19 | MB_PARITY_ODD, //奇校验 20 | MB_PARITY_EVEN //偶校验 21 | }mbParity; 22 | 23 | 24 | 25 | /** 26 | * @brief MODBUS串口初始化接口 27 | * @param baud:串口波特率 28 | * @param parity:奇偶校验位设置 29 | * @return NONE 30 | * @note 需要根据使用MCU进行移植 31 | */ 32 | void mb_port_uartInit(uint32_t baud,uint8_t parity); 33 | /** 34 | * @brief 串口TX\RX使能接口 35 | * @param txen:0-关闭tx中断 1-打开tx中断 36 | * @param rxen:0-关闭rx中断 1-打开rx中断 37 | * @return NONE 38 | * @note 需要根据使用MCU进行移植 39 | */ 40 | void mb_port_uartEnable(uint8_t txen,uint8_t rxen); 41 | /** 42 | * @brief 串口发送一个byte 43 | * @param ch:要发送的byte 44 | * @return NONE 45 | * @note 需要根据使用MCU进行移植 46 | */ 47 | void mb_port_putchar(uint8_t ch); 48 | /** 49 | * @brief 串口读取一个byte 50 | * @param ch:存放读取一个byte的指针 51 | * @return NONE 52 | * @note 需要根据使用MCU进行移植 53 | */ 54 | void mb_port_getchar(uint8_t *ch); 55 | /** 56 | * @brief 定时器初始化接口 57 | * @param baud:串口波特率,根据波特率生成3.5T的定时 58 | * @return NONE 59 | * @note 需要根据使用MCU进行移植 60 | */ 61 | void mb_port_timerInit(uint32_t baud); 62 | /** 63 | * @brief 定时器使能 64 | * @return NONE 65 | * @note 定时器要清0重新计数 66 | */ 67 | void mb_port_timerEnable(void); 68 | /** 69 | * @brief 定时器关闭 70 | * @return NONE 71 | * @note 定时器要清0重新计数 72 | */ 73 | void mb_port_timerDisable(void); 74 | 75 | #endif 76 | 77 | --------------------------------------------------------------------------------