基于STM32实现 Modbus协议调试笔记 --利用485通信实现任意字符组合的接收和发送

1)实验目的
实现STM32和电脑上位机任意字符组合的接收和发送
2)源代码
2-1:RS485.C文件中源代码
主要包括引脚功能配置函数,中断接收函数,发送和数据处理函数
#include “RS485.h”
/**


  • 文件名称: RS485.c
  • 作 者: HL
  • 版 本: V1.0
  • 编写日期: 2019-02-02
  • 功 能: 485功能配置
    ******************************************************************************/

#define RS485 USART3
ModBus_Tx ModBus_T;
u8 RS485_TX_EN=0,RS485_RX_Over;
/**

  • 函数功能: 初始化配置485通讯GPIO引脚

  • 输入参数: 无

  • 返 回 值: 无

  • 说 明:无
    */
    void RS485_GPIO_Configuration(void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    /初始化RCC_485_Pin 485控制引脚端口时钟/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//RCC_APB2Periph_GPIOB
    /初始化RCC_485_RTX 485串口通讯功能端口时钟/
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE);//RCC_APB1Periph_USART3

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//端口复用功能开启
    /初始化控制端口/
    GPIO_InitStructure.GPIO_Pin=RS485_EN_Pin;//EN_485
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
    GPIO_Init(RS485_EN_Port,&GPIO_InitStructure);
    /初始化TX端口/
    GPIO_InitStructure.GPIO_Pin=RS485_TX_Pin;//TX
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
    GPIO_Init(RS485_TX_Port,&GPIO_InitStructure);
    /初始化RX端口/
    GPIO_InitStructure.GPIO_Pin=RS485_RX_Pin;//对应于STM32的USART3_TX
    GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//推挽复用输出
    GPIO_Init(RS485_RX_Port,&GPIO_InitStructure);
    }
    /**

  • 函数功能: 初始化配置485通讯功能

  • 输入参数: USART_TypeDef* USARTx:USART功能通道;uint32_t BaudRate:波特率

  • 返 回 值: 无

  • 说 明:无
    */
    void USART_Configuration(uint32_t BaudRate)
    {
    USART_InitTypeDef USART_InitStructure;

    RS485_GPIO_Configuration();//初始化RS485 GPIO引脚

    USART_InitStructure.USART_BaudRate=BaudRate;//系统USART波特率设置
    USART_InitStructure.USART_WordLength=USART_WordLength_8b;//字长设置为8位
    USART_InitStructure.USART_StopBits=USART_StopBits_1;//在帧结尾传输一个停止位
    USART_InitStructure.USART_Parity=USART_Parity_No;//奇偶校验位设置为奇偶使能
    USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;//设置为硬件流控制失能
    USART_InitStructure.USART_Mode = USART_Mode_Tx|USART_Mode_Rx;//发送和接受均使能

    USART_Init(RS485,&USART_InitStructure);
    USART_ITConfig(RS485,USART_IT_RXNE,ENABLE);
    USART_Cmd(RS485,ENABLE);
    USART_ClearFlag(RS485,USART_FLAG_TC);//清空发送成功标志位
    RS485_EN(0);//初始化为接收状态
    RS485_TX_EN=0;//接收状态
    }

void USART3_IRQHandler(void)
{
u8 res=0;
if(USART_GetITStatus(RS485,USART_IT_RXNE)!=RESET)//检查RS485是否触发接收中断标志位
{
res=USART_ReceiveData(RS485);//将接收到的数据保存到临时变量res中
if(ModBus_T.Rx_Count<RS485_RX_BUF_LEN)
{
ModBus_T.RS485_RX_BUF[ModBus_T.Rx_Count]=res; //将接收到的数据存放到接收缓冲区内
ModBus_T.Rx_Count++;
}
}
}

//RS485发送len个字节.
//buf:发送区首地址
//len:发送的字节数(为了和本代码的接收匹配,这里建议不要超过64个字节)
void RS485_Send_Data(u8 *buf,u8 len)
{
u8 t;
RS485_TX_EN=1; //设置为发送模式
RS485_EN(1);
for(t=0;t<len;t++) //循环发送数据
{
while(USART_GetFlagStatus(RS485, USART_FLAG_TC) == RESET);
USART_SendData(RS485,buf[t]);
}

while(USART_GetFlagStatus(RS485, USART_FLAG_TC) == RESET);		
ModBus_T.Rx_Count=0;	  	//清空接收数组计数变量
RS485_TX_EN=0;				//设置为接收模式	
RS485_EN(0);
RS485_RX_Over=0;//开始下一轮接收

}
//RS485查询接收到的数据
//buf:接收缓存首地址
//返回接收到的字节数
u8 RS485_Receive_Data(u8 *buf)
{
u8 rxlen=ModBus_T.Rx_Count;
u8 i=0;
u8 len=0; //默认为0
delay_ms(10); //等待10ms,连续超过10ms没有接收到一个数据,则认为接收结束
if(rxlen==ModBus_T.Rx_Count&&rxlen)//接收到了数据,且接收完成了
{
for(i=0;i<rxlen;i++)
{
buf[i]=ModBus_T.RS485_RX_BUF[i];
}
len=ModBus_T.Rx_Count; //记录本次数据长度
ModBus_T.Rx_Count=0; //清零
RS485_RX_Over=1;//接收完成标志位置位
}
return len;

}
2-2 RS485.H中的源代码
#ifndef RS485_H
#define RS485_H

#include “stm32f10x.h”
#include “stm32f10x_usart.h”
#include “SysTick.h”
//#define RCC_485_Pin RCC_APB2Periph_GPIOB
//#define RCC_485_RTX RCC_APB1Periph_USART3

#define RS485_TX_Pin GPIO_Pin_11
#define RS485_TX_Port GPIOB

#define RS485_RX_Pin GPIO_Pin_10
#define RS485_RX_Port GPIOB

#define RS485_EN_Pin GPIO_Pin_12
#define RS485_EN_Port GPIOB

#define RS485_EN(x) x ? GPIO_SetBits(RS485_EN_Port,RS485_EN_Pin):GPIO_ResetBits(RS485_EN_Port,RS485_EN_Pin)

#define RS485_RX_BUF_LEN 64 //宏定义接收缓冲区长度,最大RS485_RX_BUF_LEN个字节

extern u8 RS485_TX_EN; //声明485通讯接收与发送模式切换标志位
//RS485_TX_EN=1;–发送模式
//RS485_TX_EN=0;–接收模式
extern u8 RS485_RX_Over;
typedef struct
{
u8 RS485_RX_BUF[RS485_RX_BUF_LEN];
u8 Rx_Count;

}ModBus_Tx;

void RS485_GPIO_Configuration(void);
void USART_Configuration(uint32_t BaudRate);
void RS485_Send_Data(u8 *buf, u8 len);
u8 RS485_Receive_Data(u8 *buf);

#endif

2-3 main函数

#include<Include.h>

int main()
{
u8 USART_RXLEN;
ModBus_Tx ModBus_T;
SystemInit();//72m
USART_Configuration(9600);//初始化USART 9600 N 8 1
NVIC_RS485_Configuration();
USART_232_Configuration(9600);
NVIC_RS232_Configuration();
while(1)
{
if(!RS485_RX_Over)
{
USART_RXLEN=RS485_Receive_Data(ModBus_T.RS485_RX_BUF);

	}
	else
		RS485_Send_Data(ModBus_T.RS485_RX_BUF,USART_RXLEN);//发送5个字节
	
}

}

发布了9 篇原创文章 · 获赞 5 · 访问量 3004

猜你喜欢

转载自blog.csdn.net/WHL_YSU/article/details/87865177