实验平台:正点原子F1战舰开发板
参考资料:《STM32F1开发指南-库函数版本_V3.3》
《STM32中文参考手册_V10》
RS232和RS485应用非常广泛,RS485是在RS232之后兴起的,常用于点对点网络中,具备以下几个特点:
接口电平低,不易损坏芯片;
传输速率高;
抗干扰能力强;
传输速率远,支持节点多;
能实现联网功能。
该开发板采用SP485作为收发器,A、 B 总线接口,用于连接 485 总线。 RO 是接收输出端, DI 是发送数据收入端, RE是接收使能信号(低电平有效), DE 是发送使能信号(高电平有效)。
硬件连接如图,PA2为USART2_TX,发送引脚;PA3为USART2_RX,接收引脚;PD7为RS485_RE,控制是收还是发,其中低电平时接收,高电平时发送(本例程仅使用RS485进行数据发送)。
第一步:配置RS485相关的GPIO引脚和串口
void RS485_Init(u32 BaudRate)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PA2-Tx(推挽复用输出)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //PA3-Rx(浮空输入)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //控制RS485的收发
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //PD7-RS485_RE(推挽输出)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &GPIO_InitStructure);
USART_InitStructure.USART_BaudRate = BaudRate; //设置波特率
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_InitStructure.USART_Parity = USART_Parity_No; //无奇偶校验
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位1
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //8位数据长度
USART_Init(USART2, &USART_InitStructure); //初始化串口
USART_Cmd(USART2, ENABLE); //串口使能
USART_ClearFlag(USART2, USART_FLAG_TC); //清除发送标志
}
RS485_Init()中主要对PA2、PA3、PD7和串口2进行初始化,PA2为发送引脚,所以配置为输出;PA3为接收引脚,所以配置为输入;PD7为控制引脚,取它的电平高低状态,所以配置为输出。(详见中文参考手册110页)
第二步:编写发送函数
void RS485_Send_Data(u8 *buf, u8 len)
{
u8 t;
RS485_TX_EN = 1; //发送模式
for(t = 0; t < len; t++)
{
while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET); //等待发送完成,USART_FLAG_TC发送完成标志,置位时表示发送完成
USART_SendData(USART2, buf[t]);
}
while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
RS485_RX_CNT = 0; //清零
}
使用***USART_FLAG_TC***发送完成标志,当其置位时,数据真正地发送出去了,此时再写入数据不易出现乱码。
第三步:编写主函数
int main(void)
{
u8 i = 0, t = 0;
u8 cnt = 0;
u8 rs485buf[5];
delay_init();
uart_init(115200);
RS485_Init(115200);
LED_Init();
delay_init();
while(1)
{
for ( i = 0; i < 5; i++)
{
rs485buf[i] = cnt + i;
}
RS485_Send_Data(rs485buf, 5);
t++;
delay_ms(10);
if (t == 5)
{
LED0 = !LED0; //提示数据正在发送
t = 0;
cnt++;
}
}
}
主函数中,定义一个数组***rs485buf[5]***存储数据,然后发送出去,先写入五个数(i),循环五次(t)后,cnt加1后再重复先前的逻辑。
第四步:实验验证
将PA2和PA3引脚与com2的收发引脚相连,5个数据为一组,循环发送5次后每个数加1再循环发送5次。
备注:因为我们只需要用RS485采集实验数据,所以本次实验仅使用了RS485接收数据的功能。