STM32
直播中

王健

7年用户 931经验值
私信 关注
[问答]

STM32H743多路串口调试经验分享

STM32H743多路串口调试经验分享

回帖(1)

李华

2021-12-8 11:15:21
一、硬件基础

  1、STM3H743核心板
2、自制串口拓展板(控制485收发使用的TDHx01D485H2隔离模块,该模块EN为低电平是发送,高电平接收)
  

  

  3、485串口模块
  
二、软件基础
从正点原子官方下载hal库例程,移植485.c文件,进行适当修改,我一共配置6个串口,以UART5对应的485_5.h和485_5.c为例进行配置:


1、RS485_5.h


#ifndef __RS485_5_H
#define __RS485_5_H
#include "sys.h"
extern u8 RS485_5_RX_BUF[64];                 /接收缓冲 可自己定义
extern u8 RS485_5_RX_CNT;                           //接收数据长度


//如果想串口中断接收,设置EN_UART5_RX为1,否则设置为0
#define EN_UART5_RX         1                        //0,不接收    1,接收


void RS485_5_Init(u32 bound);
void RS485_5_Send_Data(u8 *buf,u8 len);
void RS485_5_Receive_Data(u8 *buf,u8 *len);       
#endif


2、RS485_5.c


2.1  首先是控制RS485芯片的发送使能
1
/*  控制RS485芯片发送使能 */
#define RS485_TXEN_5_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOH_CLK_ENABLE()
#define RS485_TXEN_5_GPIO_PORT              GPIOA
#define RS485_TXEN_5_PIN                    GPIO_PIN_7


#define RS485_RX_EN_5()        RS485_TXEN_5_GPIO_PORT->BSRRL = RS485_TXEN_5_PIN
#define RS485_TX_EN_5()        RS485_TXEN_5_GPIO_PORT->BSRRH = RS485_TXEN_5_PIN


2.2 然后配置UART5中断函数
1
void UART5_IRQHandler(void)
{
    u8 res;          
    if(__HAL_UART_GET_IT(&UART5_RS485Handler,UART_IT_RXNE)!=RESET)  //接收中断
        {                
        HAL_UART_Receive(&UART5_RS485Handler,&res,1,1000);
                if(RS485_5_RX_CNT<64)
                {
                        RS485_5_RX_BUF[RS485_5_RX_CNT]=res;                //记录接收的值
                        RS485_5_RX_CNT++;                                                //接收数据增加1
                }
        }
}  


2.3 然后进行485初始化配置
1
void RS485_5_Init(u32 bound)
{
    //GPIO端口设置
        GPIO_InitTypeDef GPIO_Initure;
        __HAL_RCC_GPIOA_CLK_ENABLE();                        //使能GPIOA时钟
        __HAL_RCC_GPIOB_CLK_ENABLE();                        //使能GPIOB时钟
        __HAL_RCC_GPIOD_CLK_ENABLE();                        //使能GPIOB时钟
        __HAL_RCC_UART5_CLK_ENABLE();                        //使能UART5时钟
       
        GPIO_Initure.Pin=GPIO_PIN_6; //PB6
        GPIO_Initure.Mode=GPIO_MODE_AF_PP;                //复用推挽输出
        GPIO_Initure.Pull=GPIO_PULLUP;                        //上拉
        GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;//高速
        GPIO_Initure.Alternate=GPIO_AF14_UART5;        //复用为UART5 TX
        HAL_GPIO_Init(GPIOB,&GPIO_Initure);                   //初始化PB6
       
          GPIO_Initure.Pin=GPIO_PIN_2; //PD2
        GPIO_Initure.Mode=GPIO_MODE_AF_PP;                //复用推挽输出
        GPIO_Initure.Pull=GPIO_PULLUP;                        //上拉
        GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;//高速
        GPIO_Initure.Alternate=GPIO_AF8_UART5;        //复用为UART5 RX
        HAL_GPIO_Init(GPIOD,&GPIO_Initure);                   //初始化PD2
       
  GPIO_Initure.Pin=GPIO_PIN_7; //PA7
        GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;                //推挽输出
        GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;//高速
        HAL_GPIO_Init(GPIOA,&GPIO_Initure);                   //初始化PA7
    //UART5初始化设置
        UART5_RS485Handler.Instance=UART5;                                //UART5
        UART5_RS485Handler.Init.BaudRate=bound;                        //波特率
        UART5_RS485Handler.Init.WordLength=UART_WORDLENGTH_8B;        //字长
        UART5_RS485Handler.Init.StopBits=UART_STOPBITS_1;                //一个停止位
        UART5_RS485Handler.Init.Parity=UART_PARITY_NONE;                //无奇偶校验位
        UART5_RS485Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;        //无硬件流控制
        UART5_RS485Handler.Init.Mode=UART_MODE_TX_RX;                    //收发模式
        HAL_UART_Init(&UART5_RS485Handler);                                //HAL_UART_Init()会使能UART5
   
    __HAL_UART_CLEAR_IT(&UART5_RS485Handler,UART_CLEAR_TCF);
#if EN_UART5_RX
        __HAL_UART_ENABLE_IT(&UART5_RS485Handler,UART_IT_RXNE);//开启接收中断
        HAL_NVIC_EnableIRQ(UART5_IRQn);                                        //使能UART5中断
        HAL_NVIC_SetPriority(UART5_IRQn,3,3);                                //抢占优先级3,子优先级3
#endif       
   // RS485_RX_EN_5();  
RS485_TX_EN_5();         //设置为接收模式
}


之所以讲UART5初始化,是因为该函数有个特殊的地方,有部分STM32H743开发板使用PC12作为UART5的TX,部分威廉希尔官方网站 板使用PB6,这里需要看手册,手册中可得知,PC12复用UART5的TX是AF8,PB6复用UART5的TX是AF14,没有养成看手册的习惯,这里坑了我一天,请大家注意。


2.4 发送函数
1
void RS485_5_Send_Data(u8 *buf,u8 len)
{
        RS485_TX_EN_5();                        //低电平设置为发送模式,在上面有定义
        delay_ms(1);
    HAL_UART_Transmit(&UART5_RS485Handler,buf,len,1000);//串口2 发送数据
        RS485_5_RX_CNT=0;          
        RS485_RX_EN_5();                        //设置为接收模式
        delay_ms(1);
}


有很多人会奇怪为什么会加delay_ms(1),此处也是一个坑,由于H743处理速度太快,当波特率设置过高时,会出现丢数据情况,越高丢的越多,因为管脚状态切换反应不过来,所以加一个1ms延时,该延时可根据具体情况自行修改,一般115200bps及以下不需要加该延时。


2.5. 接收函数
1
void RS485_5_Receive_Data(u8 *buf,u8 *len)
{
        u8 rxlen=RS485_5_RX_CNT;
        u8 i=0;
        *len=0;                               
        delay_ms(10);               
        if(rxlen==RS485_5_RX_CNT&&rxlen)
        {
                for(i=0;i                 {
                        buf=RS485_5_RX_BUF;       
                }               
                *len=RS485_5_RX_CNT;       
                RS485_5_RX_CNT=0;               
        }
}


3.mian.c


int main(void)
{
        u8 rs485sendbuf5[5] = {0x51,0x53,0x55,0x58,0xff};
        u8 rs485recivebuf5[5];
        u8 length5;
        Cache_Enable();                                        //打开Li - cache
        HAL_Init();                                                        //初始化HAL库
        Stm32_Clock_Init(160,5,2,4);                      //设置时钟,400M
        delay_init(400);                                               


        //RS485_1_Init(1000000);                                       
        //RS485_2_Init(1000000);                                       
        //RS485_3_Init(1000000);                                       
        //RS485_4_Init(1000000);                                       
        RS485_5_Init(1000 000);                                       
        //RS485_6_Init(1000000);                                       
                                                                                    
        while(1)           
        {       
                RS485_5_Send_Data(rs485sendbuf5,5);       
                delay_ms(200);
                RS485_5_Receive_Data(rs485recivebuf5,&length5);
        }             
}


  三、心得

  我的工程书如下图所示:

  

  

大拿可以将六个串口整合到一块,但是我是初学者,还有待提升,大佬勿喷,这是我做的项目的一个分支,从对STM32不太熟悉,两个礼拜一直从STM32F103学习到STM32F407,再到STM32H743,从标准库到HAL库,可能还比较笼统,没有养成看手册习惯,调试没有配合硬件一起调的习惯,继续努力改进吧。希望这篇文章中关于STM32H743的串口配置和需要注意的地方能帮助到大家。
举报

更多回帖

×
20
完善资料,
赚取积分