硬汉嵌入式论坛

 找回密码
 立即注册
查看: 3172|回复: 1
收起左侧

[STM32CubeF4] 使用HAL实现的modbus串口通讯分享

[复制链接]

334

主题

2032

回帖

3039

积分

版主

Rank: 7Rank: 7Rank: 7

积分
3039
发表于 2019-8-15 09:30:16 | 显示全部楼层 |阅读模式
本帖最后由 caicaptain2 于 2019-8-15 09:34 编辑

近期开始尝试HAL库,串口收发很常用,给大家分享。
主要特点:mcu是F401,使用串口2,dma发送,中断单字节接收,tim4作为modbus的数据帧判断。不用在it函数种做任何变动。
初始化部分: tim4使用update event中断,IO口/串口设置/定时器设置简略不细说。
变量:usart2_buffe[256]串口接收缓冲;usart2_single 串口接收单字节缓冲;usart2_buffer_index缓冲区数据序号指示
main函数中,加入这个:
__HAL_TIM_ENABLE_IT(&htim4,TIM_IT_UPDATE);//打开tim4的update中断。tim4的总中断在初始化时已经打开。
HAL_UART_Receive_IT(&huart2,&usart2_single,1)//打开串口接收中断。

串口DMA发送用这个:
    while(huart2.gState == HAL_UART_STATE_READY)
    {
     HAL_GPIO_WritePin(ModbusControl_GPIO_Port,ModbusControl_Pin,GPIO_PIN_SET);//设置modbus为发送模式。半双工用这个,全双工忽略。
     HAL_UART_Transmit_DMA(&huart2,发送缓冲区指针,数据长度);//使能串口发送DMA
    }

回调函数部分:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) //串口接收中断回调函数
{
if (huart->Instance ==USART2 ) {
   usart2_buffe[usart2_buffer_index]=usart2_single;
   HAL_UART_Receive_IT(huart,&usart2_single,1); //使能串口2的接受中断,每次接收一个就中断,且进入complete回调函数
        if(usart2_buffer_index==0)   {
        __HAL_TIM_SET_COUNTER(&htim4, 0);//此处应该计数器清零先
       HAL_TIM_Base_Start(&htim4);//HAL函数方式
      //__HAL_TIM_ENABLE(&htim4); 寄存器方式
        }
        //此处TIM4->CNT可以赋值为2ms,来满足modbus 字节之间小于1.5t延时标准。
    __HAL_TIM_SET_COUNTER(&htim4, 0);
     ModbusOvertime=0; //
        usart2_buffer_index++; //数据超长
        if(usart2_buffer_index>(USARTBUFFERSIZE-1))
        {
            usart2_buffer_index=0;    //1-3
        }
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//TIM11是FreeRTOS的时钟,为系统自动加上的。
{
  /* USER CODE BEGIN Callback 0 */
  if (htim->Instance == TIM4) {//TIM4的超时,判断出一帧数据结束,然后停止定时器。
  __HAL_TIM_SET_COUNTER(&htim4, 0);
     ModbusOvertime=1;//超时后,才可以判断一帧结束,解码。
   HAL_TIM_Base_Stop(&htim4);
  //__HAL_TIM_DISABLE(&htim4); //寄存器操作方式
  }
  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM11) {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */
  /* USER CODE END Callback 1 */
}
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)//这个是收发的IO口控制,RS485半双工中使用。
{
if (huart->Instance ==USART2 ) {
  HAL_GPIO_WritePin(ModbusControl_GPIO_Port,ModbusControl_Pin,GPIO_PIN_RESET);//设置modbus为接收模式。
}
}

评分

参与人数 1金币 +50 收起 理由
eric2013 + 50 赞一个!

查看全部评分

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106749
QQ
发表于 2019-8-15 11:03:37 | 显示全部楼层
非常感谢楼主分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-4 09:00 , Processed in 0.147945 second(s), 26 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表