STM32L4-双路RS485自收发通信实验[寄存器版]

485基本介绍

485通信协议是一种常用的半双工串行通信协议,具有抗干扰能力强,传输距离远等特点,因此在工业及自动化领域被广泛运用。

由于485属于半双工通讯,因此不能同时进行接收和发送,需要配置485控制芯片切换为发送或者接收状态。

以ADM3485芯片为例:

依据真值表所示,传统的RS485收发电路通常将收发控制引脚RE和DE连接在一起,通过一个IO口的高低电平变化进行控制收发。

当MCU需要向外发送数据的时候,配置R/D引脚为高电平

当MCU需要向内接收数据的时候,配置R/D引脚为低电平

因此,抛开硬件层面的区别,在软件层面,RS485可以理解为串口通信+一组收发控制引脚。

那么,RS485的配置过程也与串口类似,只需要进行一些修改即可。

基本配置

MCU采用STM32L431RCT6

485芯片采用ADM3485

本次使用STM32L4芯片的串口USART3和串口USART1通过两路RS485进行自收发通信实验

配置PB10,PB11为USART3 ,控制引脚PC6;

配置PA9,PA10为USART1 ,控制引脚PA11;

串口初始化函数

这里我配置了一个通用的初始化函数,可以根据需求配置串口,中断,中断优先级与波特率:

/*********485-通用串口初始化函数******************/
void RS485_init(USART_TypeDef* USARTX,IRQn_Type IRQn,uint8_t priority,uint32_t baud)//串口,中断,中断优先级,波特率
{
	USARTX->CR1=0;//初始化寄存器
	USARTX->CR2=0;
	USARTX->CR3=0;
	
	CLEAR_BIT(USARTX->CR1,USART_CR1_OVER8);//过采样16
	CLEAR_BIT(USARTX->CR1,USART_CR1_M0);//1个起始位8个数据位
	CLEAR_BIT(USARTX->CR1,USART_CR1_M1);
	CLEAR_BIT(USARTX->CR2,USART_CR2_STOP);//1个停止位
	CLEAR_BIT(USARTX->CR1,USART_CR1_PCE);//禁用奇偶校验控制
//	SET_BIT(USARTX->CR1,USART_CR1_PCE);//奇偶校验使能
//	SET_BIT(USARTX->CR1,USART_CR1_PS);//奇校验
	USARTX->BRR=16000000/baud;//波特率
//	SET_BIT(USARTX->CR2,USART_CR2_ABRMODE);
//	SET_BIT(USARTX->CR2,USART_CR2_ABREN);//自动波特率检测
	
    NVIC_DisableIRQ(IRQn);//关中断
 	SET_BIT(USARTX->CR1,USART_CR1_RXNEIE);//设置RXNE中断
//	SET_BIT(USARTX->CR1,USART_CR1_IDLEIE);//设置IDLE中断
	
//	SET_BIT(USARTX->CR1,USART_CR1_TXEIE);//发送缓冲区空中断使能
//	SET_BIT(USARTX->CR1,USART_CR1_TCIE);//发送完成中断使能

 	NVIC_SetPriority(IRQn,priority);//设置中断优先级
 	NVIC_EnableIRQ(IRQn);//开中断
//	SET_BIT(USARTX->CR3,USART_CR3_DMAR);//开启DMA接收通道
//	SET_BIT(USARTX->CR3,USART_CR3_DMAT);//开启DMA发送通道
	SET_BIT(USARTX->CR1,USART_CR1_TE);//使能发送接收
	SET_BIT(USARTX->CR1,USART_CR1_RE);
	SET_BIT(USARTX->CR1,USART_CR1_UE);//开串口
	if(USARTX==USART1)
	{
		RE_DE_RX1;//初始化默认为接收状态
	}
	else if(USARTX==USART3)
	{
		RE_DE_RX3;//初始化默认为接收状态
	}
}

波特率配置

依据芯片编程手册:

当过采样为16(OVER8=0)时,波特率为Fck(系统总线时钟)/USARTDIV(波特率分频系数)

这里我已经将系统时钟配置为16MHZ的内部时钟HSI16:

SET_BIT(RCC->CFGR,RCC_CFGR_SWS_0);//配置时钟源为HSI16
SET_BIT(RCC->CFGR,RCC_CFGR_SW_0);
// 使能 HSI 时钟
RCC->CR |= RCC_CR_HSION;
// 等待 HSI 稳定
while (!(RCC->CR & RCC_CR_HSIRDY)) {
    // 等待 HSI 稳定
};

 因此直接往BRR寄存器中写入对应值即可:USARTX->BRR=16000000/baud;//波特率

RS485接收中断配置函数

本次使用基于RS485的串口USART3发送数据,串口USART1接收数据。因此,使用RXNE中断时,配置USART1中断。当接收缓冲寄存器RDR非空的时候,表示串口接收到了数据,此时触发RXNE中断,在中断函数中将RDR中的值取出并储存在预设的数组中:

//USART1串口中断服务函数
//产生RXNE中断时,将usart1接收到的数据发送到缓存接收函数RX_BUF中。
void USART1_IRQHandler()
{
	//485接收数据,由USART3发送USART1接收,实现自收发
	uint8_t RES;
	if(READ_BIT(USART1->ISR,USART_ISR_RXNE))
	{
		RES=USART1->RDR &(uint16_t)0x01FF;//保存接收到的数据
		if(RX_CNT<64)
		{
			RX_BUF[RX_CNT]=RES;//将接收到的字节每一位都存入RX_BUF里
			RX_CNT++;//接收计数器+1
		}
	}
}

RS485发送配置函数

RS485发送数据与串口基本相同,调用该函数的时候将485控制引脚R/D配置为发送状态,通过发送完成状态寄存器TC检测TDR寄存器中的值是否已经全部发送完成。

在发送完成后,将R/D引脚配置回默认接收状态。

//485发送数据
void RS485_Send_Data(USART_TypeDef* USARTX,uint8_t *buf,uint8_t len)
{
	if(USARTX==USART1)
	{
		RE_DE_TX1;			//设置为发送模式
	}
	else if(USARTX==USART3)
	{
		RE_DE_TX3;			//设置为发送模式
	}
	uint8_t t;
  	for(t=0;t<len;t++)		//循环发送数据
	{
		while(READ_BIT(USARTX->ISR,USART_ISR_TC)==0);
		USARTX->TDR=buf[t] &(uint16_t)0x01FF ;//数据放入传输数据寄存器
//		USARTX->TDR=buf[t];
	} 
	while(READ_BIT(USARTX->ISR,USART_ISR_TC)==0){};
		if(USARTX==USART1)
	{
		RE_DE_RX1;			//设置为接收模式
	}
	else if(USARTX==USART3)
	{
		RE_DE_RX3;			//设置为接收模式
	}
}

主函数配置

485收发引脚配置与串口配置相同,这里忽略。

开启usart1和usart3时钟:

	SET_BIT(RCC->APB2ENR,RCC_APB2ENR_USART1EN);//开usart1时钟
	SET_BIT(RCC->APB1ENR1,RCC_APB1ENR1_USART3EN);//开usart3时钟

开启两个RS485通讯接口,波特率配置为9600:

	RS485_init(USART1,USART1_IRQn,2,9600);
	RS485_init(USART3,USART3_IRQn,1,9600);

创建待发送数据数组,并填入要发送的数据:

这里配置发送两个字节数据0x04和0x02

uint8_t TCOM[2]={0x04,0x02};

发送数据:

RS485_Send_Data(USART3,TCOM,3);

最后,将接收数组RX_BUF中的两个字节数据以十进制形式分别显示在LCD液晶屏上:

可以看到接收数组中的显示数据与预先设置的发送数据一致, RS485自收发实验成功。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值