ATK-MB024 485模块使用说明
这里以正点原子M48Z-M3最小系统板STM32F103版为例,给大家介绍一下模块和板卡的连接方法。其它板卡与模块的硬件连接方法,请大家在“ATK-MB024 485模块\3,程序源码\相应板卡例程文件夹\readme.txt”路径下查看。
ATK-MB024 485模块可通过杜邦线与正点原子M48Z-M3最小系统板STM32F103版进行连接,具体的连接关系,如下表所示:

表1.1 485模块与M48Z-M3最小系统板STM32F103版连接关系
值得注意的是,要实现RS485通信,则需两套相关的设备,例如:两块STM32F103最小系统板+两个ATK-MB024 485模块。通信的时候,两个485模块的连接关系如下表所示:

表1.2 两个485模块之间的连接关系
在本实验中,串口会打印485模块发送或接收到的数据。需要查看这部分实验信息的用户,可用杜邦线将最小系统板STM32F103的PA9引脚和GND连接至外部的USB转串口设备,这样就可以通过XCOM上位机查看串口打印的信息了。
当KEY0按键被按下时,485模块会往外发送一次数据,数据量为200个字节,数据内容随机。当485模块接收到数据时,会自动将数据打印到串口。
用户可以通过拨动开关选择是否开启120Ω终端电阻,ON档即开启,OFF档即关闭。
开发板的LED0闪烁,提示程序运行。
打开本实验的工程文件夹,能够在./Drivers/BSP目录下看到ATK_RS485文件夹,其包含了ATK-MB024 485模块的驱动文件,如下图所示:

图2.1.2.1 ATK-MB024 485模块驱动代码
下面简要介绍atk_rs485.c中几个重要的API函数。
1. 函数atk_rs485_init()
该函数用于初始化ATK-MB024 485模块,具体的代码,如下所示:
/**
* @brief ATK_RS485模块初始化函数
* @note 该函数主要是初始化串口
* @param baudrate: 波特率, 根据自己需要设置波特率值
* @retval 无
*/
void atk_rs485_init(uint32_t baudrate)
{
GPIO_InitTypeDef gpio_init_struct;
ATK_RS485_TX_GPIO_CLK_ENABLE(); /* 使能 串口TX脚 时钟 */
ATK_RS485_RX_GPIO_CLK_ENABLE(); /* 使能 串口RX脚 时钟 */
ATK_RS485_UX_CLK_ENABLE(); /* 使能 串口 时钟 */
/* 串口TX引脚初始化 */
gpio_init_struct.Pin = ATK_RS485_TX_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_AF_PP;
gpio_init_struct.Pull = GPIO_PULLUP;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(ATK_RS485_TX_GPIO_PORT, &gpio_init_struct);
/* 串口RX引脚初始化 */
gpio_init_struct.Pin = ATK_RS485_RX_GPIO_PIN;
gpio_init_struct.Mode = GPIO_MODE_AF_INPUT;
HAL_GPIO_Init(ATK_RS485_RX_GPIO_PORT, &gpio_init_struct);
/* USART 初始化设置 */
g_rs458_handler.Instance = ATK_RS485_UX; /* 选择485对应的串口 */
g_rs458_handler.Init.BaudRate = baudrate; /* 波特率 */
/* 字长为8位数据格式 */
g_rs458_handler.Init.WordLength = UART_WORDLENGTH_8B;
g_rs458_handler.Init.StopBits = UART_STOPBITS_1; /* 一个停止位 */
g_rs458_handler.Init.Parity = UART_PARITY_NONE; /* 无奇偶校验位 */
g_rs458_handler.Init.HwFlowCtl = UART_HWCONTROL_NONE; /* 无硬件流控 */
g_rs458_handler.Init.Mode = UART_MODE_TX_RX; /* 收发模式 */
HAL_UART_Init(&g_rs458_handler); /* HAL_UART_Init()会使能UART2 */
#if RS485_EN_RX /* 如果使能了接收 */
__HAL_UART_ENABLE_IT(&g_rs458_handler, UART_IT_RXNE); /* 开启接收中断 */
HAL_NVIC_EnableIRQ(ATK_RS485_UX_IRQn); /* 使能USART2中断 */
HAL_NVIC_SetPriority(ATK_RS485_UX_IRQn, 3, 3); /* 抢占优先级3,子优先级3 */
#endif
}
atk_rs485_init()函数并不复杂,它就是对485模块相关串口及引脚进行初始化配置,这里使用的串口为串口2,TX引脚为PA2,RX引脚为PA3,波特率由函数的入口参数决定。
2. 函数atk_rs485_send_data()
该函数用于485模块发送数据,具体代码,如下所示:
/**
* @brief RS485发送len个字节数据
* @param buf : 缓冲区指针
* @param len : 发送的字节数(为了和本代码的接收匹配,这里建议不要超过 RS485_REC_LEN 个字节)
* @retval 无
*/
void atk_rs485_send_data(uint8_t *buf, uint8_t len)
{
HAL_UART_Transmit(&g_rs458_handler, buf, len, 1000); /* 串口发送数据 */
g_RS485_rx_cnt = 0; /* 清空计数 */
}
该函数通过调用HAL_UART_Transmit()函数来发送串口数据,具体的数据内容和长度由函数入口参数决定。
3. 函数atk_rs485_receive_data()
该函数用于485模块接收数据,具体代码,如下所示:
/**
* @brief RS485查询接收到的数据
* @param buf : 接收缓冲区首地址
* @param len : 接收到的数据长度
* @arg 0,表示没有接收到任何数据
* @arg 其他, 表示接收到的数据长度
* @retval 无
*/
void atk_rs485_receive_data(uint8_t *buf, uint8_t *len)
{
uint8_t rxlen = g_RS485_rx_cnt;
uint8_t i = 0;
*len = 0; /* 默认为0 */
delay_ms(5); /* 等待5ms,连续超过5ms没有接收到一个数据,则认为接收结束 */
if (rxlen == g_RS485_rx_cnt && rxlen) /* 接收到了数据,且接收完成了 */
{
for (i = 0; i < rxlen; i++)
{
buf[i] = g_RS485_rx_buf[i]; /* 取出数据,保存到buf中 */
}
*len = g_RS485_rx_cnt; /* 记录本次数据长度 */
g_RS485_rx_cnt = 0; /* 清零 */
}
}
进入到上述函数中,先读取并记录g_RS485_rx_cnt的值,然后延时5ms,接着再次读取g_RS485_rx_cnt的值,如果前后两次的值相同,则说明没有新的数据进来了。与此同时,rxlen不为0,则可以开始读出数据了。
读出的数据会被保存到接收缓冲区中,该缓冲区的地址由函数入口参数决定。
实验的测试代码在demo.c文件中,该文件在工程根目录下的 User文件夹。测试代码的入口函数为demo_run(),具体的代码,如下所示:
/**
* @brief 例程演示入口函数
* @param 无
* @retval 无
*/
void demo_run(void)
{
uint8_t key;
uint8_t i = 0, t = 0;
uint8_t cnt = 0;
uint8_t rs485buf[200];
atk_rs485_init(256000); /* 初始化RS485,波特率256000 */
while (1)
{
key = key_scan(0);
if (key == KEY0_PRES) /* KEY0按下,发送一次数据 */
{
printf("RS485模块 发送的数据为:");
for (i = 0; i < 200; i++)
{
rs485buf[i] = cnt + i; /* 填充发送缓冲区 */
printf("%02X", rs485buf[i]); /* 打印输出数据 */
}
printf("\r\n");
atk_rs485_send_data(rs485buf, 200); /* 发送200个字节 */
}
atk_rs485_receive_data(rs485buf, &key);
if (key) /* 接收到数据 */
{
if (key > 200)key = 200; /* 最大有效字节数:200个 */
printf("RS485模块 接收的数据为:");
for (i = 0; i < key; i++)
{
printf("%02X", rs485buf[i]); /* 打印输出数据 */
}
printf("\r\n");
}
t++;
delay_ms(10);
if (t == 20)
{
LED0_TOGGLE(); /* LED0闪烁, 提示系统正在运行 */
t = 0;
cnt++;
}
}
}
从上面代码可以看出,整个测试代码的逻辑相对简单。首先初始化485模块相关的串口,波特率为256000,接着在while循环中不断地扫描按键状态以及获取接收的数据。
当KEY0按键被按下后,485模块将会发送200个字节的随机数据,与此同时,串口会打印这些已发送的数据;当485模块接收到数据后,也会通过串口进行打印。LED0闪烁表示程序正常运行。
将ATK-MB024 485模块按照第一节“硬件连接”中介绍的连接方式与开发板连接,并将实验代码编译烧录至开发板中。值得注意的是,要实现RS485通信,则需两套相关的设备,例如:两块STM32F103最小系统板+两个ATK-MB024 485模块。两块开发板都烧录本实验代码,两个485模块的接线端子A接A,B接B,GND接GND。
本实验使用串口输出调试信息,因此需将开发板的PA9连接至DAP虚拟串口(或USB转TTL模块)的RX引脚。完成连接后,可通过串口调试助手XCOM查看实验信息输出,如下图所示:

图2.1.3.1串口调试助手显示内容
注:其它现象请看2.1.1功能说明。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70040860/viewspace-3082121/ ,如需转载,请注明出处,否则将追究法律责任。