一、硬件基础
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的串口配置和需要注意的地方能帮助到大家。
一、硬件基础
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的串口配置和需要注意的地方能帮助到大家。
举报