基于stm32hal库开发的485通讯模块

头文件HDL_RS485.H

/**
  ******************************************************************************
  * @file    HDL_RS485.H
  * @brief   485通信硬件驱动D的头文件
  *         该头主要包括定义的类的变量,以及对外的变量接口,和行为接口(接口函数)。    
  * */
/*******************************************************************************
**                             Author(s) Identity                             **
**                             维护人员列表                                     **
********************************************************************************
** Initials     Name                                                          **
** ---------------------------------------------------------------------------**

*******************************************************************************/

/*******************************************************************************
**                         Revision Control History                           **
********************************************************************************
**@version        初始版本需求                             **
**@version        初始版本                             **
*******************************************************************************/
#ifndef _HDL_RS485_H
#define _HDL_RS485_H

#include "stm32f1xx_hal.h"


#define  TX_MODE  0x01
#define  RX_MODE  0x00

#define  TX_BUSY 0x01
#define  TX_IDLE  0x00
#define  RX_BUF_EMPTY 0x00
#define  RX_BUF_READY 0x01

#define  RS485_NUM     1       //硬件中,RS485模块的数量  

typedef struct 
{
    GPIO_TypeDef*   RxOrTxEN_Port;             //  Hal库结构体  RXEN,and TXEN 连接到1个引脚
    const uint16_t  RxOrTxEN_Gpio_Pin;       //  RXEN,and TXEN 连接到1个引脚
    GPIO_TypeDef*   Rx_Port;                   //  Hal库结构体  RX引脚的port
    const uint16_t  Rx_Gpio_Pin;             //  RX引脚的pin
    GPIO_TypeDef*   Tx_Port;                   //  Hal库结构体  TX引脚的port
    const uint16_t  Tx_Gpio_Pin;             //  TX引脚的pin
    USART_TypeDef*  Uart_Channel;           //  Hal库结构体  串口号选择 
    const uint32_t  baudrate;                      //  波特率
    uint8_t mode;                                 //  Rx mode 0x00 or TX MODE 0x01 ,接收模式或发送模式,默认接收模式
    uint8_t TxState;                              //  Busy 0x01 or idle 0x00 ,忙碌状态(正在发送),或空闲状态,默认空闲状态
    uint8_t RxBuffer;                             //  485接收数据的内容,默认0x00;
    uint8_t RxBufferstate;                        //  接收完成 0x01  接收缓存空:0x00,ready 0x01 or empty 0x00
} TypeDef_HDL_RS485;


/****HDL_PORT FUNCTION******/
uint8_t HDL_RS485_Init(TypeDef_HDL_RS485 *this_485);
uint8_t HDL_RS485_SetMode(TypeDef_HDL_RS485 *this_485, uint8_t RxOrTxMode);
uint8_t HDL_RS485_GetMode(TypeDef_HDL_RS485 *this_485);

uint8_t HDL_RS485_GetTxState(TypeDef_HDL_RS485 *this_485);
uint8_t HDL_RS485_SetTxState(TypeDef_HDL_RS485 *this_485, uint8_t TxState);

uint8_t HDL_RS485_RecData(TypeDef_HDL_RS485 *this_485);
uint8_t HDL_RS485_TransData(TypeDef_HDL_RS485 *this_485,uint8_t TxData);
void HDL_RS485_uart_IRQ_Task(void);

/****HDL_PORT GlobalParameter******/
extern TypeDef_HDL_RS485 RS485_1;  
extern TypeDef_HDL_RS485 RS485_2;
extern UART_HandleTypeDef  RS481_1_UartHandle;

#endif /* _HDL_RS485_H */

C文件HDL_RS485.C

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    HDL_RS485.c
  * @brief   485通信硬件驱动
  *         该硬件模块是实现485收发通信,属于数据链路层的驱动。
  *                   使用STM32串口模块实现485功能,并使用GPIO控制芯片引脚工作在相应的模式下。
  *         驱动要求:1、能够配置485的状态,并在串口收发中断中执行。
  *                  2、要求能配置控制485的引脚使模块处在接收,或发送状态。
  *                  3、要求能查询485通信状态: 收缓存区,发缓存区是否为空。
  *                                          收发数据时,状态置为0x01,数据取走后,软件置0x00
  *                  4、要求能够返回485通信接收值
  *                  5、可以具备STM32串口模块具备的其他功能
  * @todo                                 
  * */
 /*******************************************************************************
**                             Author(s) Identity                              **
**                             维护人员列表                                     **
********************************************************************************
** Initials     Name                                                          **
** ---------------------------------------------------------------------------**
**                                                                         **
*******************************************************************************/

/*******************************************************************************
**  2-Revision Control History                                                **
**  2-版本维护历史                                                              **
********************************************************************************
**@version                      **
**@version                                  **
*******************************************************************************/

/* 3-Includes ----------------------------------------------------------------*/
#include "HDL_RS485.h"

/* 4-define ------------------------------------------------------------------*/
#define HARD_WARE_VERSION 

#define HDL_RS485_uart_IRQ_Task		USART1_IRQHandler //串口中断号重命名
#define RS485_NUM     1       //硬件中,RS485模块的数量         

//模块1的属性宏定义,关联到HAL库
#define M1_RXOrTXEN_GPIO_PORT  GPIOC       //  RXEN,and TXEN 连接到1个引脚
#define M1_RXOrTXEN_GPIO_PIN   GPIO_PIN_4       //  RXEN,and TXEN 连接到1个引脚
#define M1_RX_GPIO_PORT        GPIOA       //  RX
#define M1_RX_GPIO_PIN         GPIO_PIN_10       //  RX
#define M1_TX_GPIO_PORT        GPIOA       //  TX
#define M1_TX_GPIO_PIN         GPIO_PIN_9       //  RX
#define M1_UART                USART1       //  关联到HAL库

//模块2的属性宏定义,关联到HAL库
#define M2_RXOrTXEN_GPIO_PORT  GPIOC       //  RXEN,and TXEN 连接到1个引脚
#define M2_RXOrTXEN_GPIO_PIN   GPIO_PIN_4        //  RXEN,and TXEN 连接到1个引脚
#define M2_RX_GPIO_PORT        GPIOA       //  RX
#define M2_RX_GPIO_PIN         GPIO_PIN_10       //  RX
#define M2_TX_GPIO_PORT        GPIOA       //  TX
#define M2_TX_GPIO_PIN         GPIO_PIN_9       //  RX
#define M2_UART                USART1       //  关联到HAL库

//RS485模块一串口句柄全局定义
UART_HandleTypeDef  RS481_1_UartHandle;

/* 5-function declaration -----------------------------------------------------*/
// 5.1-Public_function declaration --------------------------------------------
uint8_t HDL_RS485_Init(TypeDef_HDL_RS485 *this_485);
uint8_t HDL_RS485_SetMode(TypeDef_HDL_RS485 *this_485, uint8_t RxOrTxMode);
uint8_t HDL_RS485_GetMode(TypeDef_HDL_RS485 *this_485);

uint8_t HDL_RS485_GetTxState(TypeDef_HDL_RS485 *this_485);
uint8_t HDL_RS485_SetTxState(TypeDef_HDL_RS485 *this_485, uint8_t TxState);

uint8_t HDL_RS485_RecData(TypeDef_HDL_RS485 *this_485);
uint8_t HDL_RS485_TransData(TypeDef_HDL_RS485 *this_485,uint8_t TxData);

void HDL_RS485_uart_IRQ_Task(void);

// 5.2-privace_function declaration --------------------------------------------

/* 6-parameter declaration and initial ---------------------------------------*/
 TypeDef_HDL_RS485 RS485_1 = 
 {
  .RxOrTxEN_Port      = M1_RXOrTXEN_GPIO_PORT,
  .RxOrTxEN_Gpio_Pin  = M1_RXOrTXEN_GPIO_PIN,
  .Rx_Port            = M1_RX_GPIO_PORT,
  .Rx_Gpio_Pin        = M1_RX_GPIO_PIN,
  .Tx_Port            = M1_TX_GPIO_PORT,
  .Tx_Gpio_Pin        = M1_TX_GPIO_PIN,
  .Uart_Channel       = M1_UART,
  .baudrate           = 9600,
  .mode               = RX_MODE,
  .TxState            = TX_IDLE,
  .RxBufferstate      = RX_BUF_EMPTY,
  .RxBuffer           = 0x00,
 };

 TypeDef_HDL_RS485 RS485_2 = 
 {
  .RxOrTxEN_Port      = M2_RXOrTXEN_GPIO_PORT,
  .RxOrTxEN_Gpio_Pin  = M2_RXOrTXEN_GPIO_PIN,
  .Rx_Port            = M2_RX_GPIO_PORT,
  .Rx_Gpio_Pin        = M2_RX_GPIO_PIN,
  .Tx_Port            = M2_TX_GPIO_PORT,
  .Tx_Gpio_Pin        = M2_TX_GPIO_PIN,
  .Uart_Channel       = M2_UART,
  .baudrate           = 9600,
  .mode               = RX_MODE,
  .TxState            = TX_IDLE,
  .RxBufferstate      = RX_BUF_EMPTY,
  .RxBuffer           = 0x00,
 };


/* 7-function declaration and initial ---------------------------------------*/



 /**
  * @name   uint8_t HDL_RS485_Init(TypeDef_HDL_RS485 *this_485);
  * @brief  初始化485模块的变量和状态
  *         初始化485模式:读模式
  *         初始化485发送状态:空闲
  * @param  this_485 指针型结构体,指向TypeDef_HDL_RS485类型的结构体对象,
  *         1个485模块一个结构体,方便操作多个485模块
  * 
  * @retval uint8_t result  ,0x00,初始化成功。
  *                         0x01,初始化失败。
  *                         可以细化更多初始化失败码
  */
uint8_t HDL_RS485_Init(TypeDef_HDL_RS485 *this_485)
 {
    RS481_1_UartHandle.Instance = this_485->Uart_Channel;
    RS481_1_UartHandle.Init.BaudRate = this_485->baudrate;
    RS481_1_UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
    RS481_1_UartHandle.Init.StopBits = UART_STOPBITS_1;
    RS481_1_UartHandle.Init.Parity = UART_PARITY_NONE;
    RS481_1_UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    RS481_1_UartHandle.Init.Mode = UART_MODE_TX_RX;

    HAL_UART_Init(&RS481_1_UartHandle);

    __HAL_UART_ENABLE_IT(&RS481_1_UartHandle,UART_IT_RXNE);  

    if(RS481_1_UartHandle.Instance == this_485->Uart_Channel && RS481_1_UartHandle.Init.BaudRate == this_485->baudrate)
    {
      return (0x00);
    }
    else
    {
      return (0x01);
    }
 }

 /**
  * @name   HAL_UART_MspInit(UART_HandleTypeDef *huart);
  * @brief  UART MSP 初始化,UART初始化时会调用该重定向函数
  * @param  huart 指针型结构体,指向所用的串口句柄
  * @retval 无
  */
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
  GPIO_InitTypeDef GPIO_InitStruct;

   __HAL_RCC_USART1_CLK_ENABLE();
   __HAL_RCC_GPIOA_CLK_ENABLE();
   __HAL_RCC_GPIOC_CLK_ENABLE();

   /* 配置Tx引脚为复用功能 */ 
   GPIO_InitStruct.Pin = RS485_1.Tx_Gpio_Pin;
   GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
   GPIO_InitStruct.Pull = GPIO_PULLUP; 
   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
   HAL_GPIO_Init(RS485_1.Tx_Port, &GPIO_InitStruct);

   /* 配置Rx引脚为复用功能 */
   GPIO_InitStruct.Pin = RS485_1.Rx_Gpio_Pin;
   GPIO_InitStruct.Mode=GPIO_MODE_AF_INPUT;
   HAL_GPIO_Init(RS485_1.Rx_Port, &GPIO_InitStruct);

   /* 配置EN引脚为推挽输出功能 */
   GPIO_InitStruct.Pin = RS485_1.RxOrTxEN_Gpio_Pin;
   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
   GPIO_InitStruct.Pull = GPIO_PULLUP;
   GPIO_InitStruct.Speed =  GPIO_SPEED_FREQ_HIGH;
   HAL_GPIO_Init(RS485_1.RxOrTxEN_Port, &GPIO_InitStruct);

   HAL_NVIC_SetPriority(USART1_IRQn ,0,1);	//抢占优先级0,子优先级1
   HAL_NVIC_EnableIRQ(USART1_IRQn);		//使能USART1中断通道 
}


 /**
  * @name   uint8_t HDL_RS485_SetMode(TypeDef_HDL_RS485 *this_485, uint8_t RxOrTxMode);
  * @brief  设置485模块的使能引脚,切换模式,模式包括:接收模式,发送模式两种,
  *         根据是否正在发送,来判断是否切换模式。
  * @param  this_485 指针型结构体,指向TypeDef_HDL_RS485类型的结构体对象,
  *         1个485模块一个结构体,方便操作多个485模块
  * @param  uint8_t RxOrTxMode  ,0x00,接收模式。
  *                             0x01,发送模式,
  * 
  * @retval  uint8_t result  ,0x00,执行成功。
  *                          0x01,执行失败。
  *                         可以细化更多失败码
  */
uint8_t HDL_RS485_SetMode(TypeDef_HDL_RS485 *this_485, uint8_t RxOrTxMode)
{
  switch(RxOrTxMode)
  {
    case TX_MODE:
      HAL_Delay(500);
      HAL_GPIO_WritePin(this_485->RxOrTxEN_Port, this_485->RxOrTxEN_Gpio_Pin, GPIO_PIN_SET);
      HAL_Delay(500);
      this_485->mode = TX_MODE;
      return (0x00);
    case RX_MODE:
      HAL_Delay(500);
      HAL_GPIO_WritePin(this_485->RxOrTxEN_Port, this_485->RxOrTxEN_Gpio_Pin, GPIO_PIN_RESET);
      HAL_Delay(500);
      this_485->mode = RX_MODE;
      return (0x00);
    default:
      return (0x01);
  }
}


 /**
  * @name   HDL_RS485_GetMode(TypeDef_HDL_RS485 *this_485);
  * @brief  获取485模块的状态(读取引脚),状态包括:接收状态,发送状态两种
  * @param  this_485 指针型结构体,指向TypeDef_HDL_RS485类型的结构体对象,
  *         1个485模块一个结构体,方便操作多个485模块
  * 
  * @retval uint8_t RxOrTxMode  ,0x00,接收模式。
  *                             0x01,发送模式,
  */
uint8_t HDL_RS485_GetMode(TypeDef_HDL_RS485 *this_485)
{
    return (this_485->mode);
}


/**
  * @name   uint8_t HDL_RS485_GetTxState(TypeDef_HDL_RS485 *this_485);
  * @brief  获取485模块1的状态,
  *         状态包括:忙碌状态(正在发送)
  *                  或空闲状态,默认空闲状态
  * @param  this_485 指针型结构体,指向TypeDef_HDL_RS485类型的结构体对象,
  *         1个485模块一个结构体,方便操作多个485模块
  * 
  * @retval uint8_t TxState  ,0x00,空闲
  *                          0x01,正在发送
  */
uint8_t HDL_RS485_GetTxState(TypeDef_HDL_RS485 *this_485)
{
    return (this_485->TxState);
}



/**
  * @name   uint8_t HDL_RS485_SetTxState(TypeDef_HDL_RS485 *this_485, uint8_t TxState);
  * @brief  设置485模块1的状态,
  *         状态包括:忙碌状态(正在发送)
  *                  或空闲状态,默认空闲状态
  * @param  this_485 指针型结构体,指向TypeDef_HDL_RS485类型的结构体对象,
  *         1个485模块一个结构体,方便操作多个485模块
  * @param  uint8_t TxState  ,0x00,空闲
  *                          0x01,正在发送
  * @retval uint8_t result  ,0x00,执行成功。
  *                         0x01,执行失败。  
  */
uint8_t HDL_RS485_SetTxState(TypeDef_HDL_RS485 *this_485, uint8_t TxState)
{
  switch(TxState)
  {
    case TX_IDLE:
      this_485->TxState = TX_IDLE;
      return (0x00);
    case TX_BUSY:
      this_485->TxState = TX_BUSY;
      return (0x00);
    default:
      return (0x01);
  }
}



 /**
  * @name   uint8_t HDL_RS485_RecData(TypeDef_HDL_RS485 *this_485);
  * @brief  读取485模块接收缓存的结果,并将缓存标志位清零
  *         
  * @param  this_485 指针型结构体,指向TypeDef_HDL_RS485类型的结构体对象,
  *         1个485模块一个结构体,方便操作多个485模块
  * 
  * @retval uint8_t RxData  返回缓存值
  */

uint8_t HDL_RS485_RecData(TypeDef_HDL_RS485 *this_485)
{ 
  this_485->RxBufferstate = RX_BUF_EMPTY;
  return (this_485->RxBuffer);
}



 /**
  * @name   uint8_t HDL_RS485_1_TxData(uint8_t TxData);
  * @brief  通过485发送串口数据
  *         
  * @param  this_485 指针型结构体,指向TypeDef_HDL_RS485类型的结构体对象,
  *         1个485模块一个结构体,方便操作多个485模块
  * @param  uint8_t TxData  ,待发送数据
  * 
  * @retval uint8_t result      0x00,执行成功。
  *                           0x01,执行失败。
  */
uint8_t HDL_RS485_TransData(TypeDef_HDL_RS485 *this_485,uint8_t TxData)
{
  if(this_485->Uart_Channel == RS481_1_UartHandle.Instance)
  {
    HAL_UART_Transmit(&RS481_1_UartHandle,(uint8_t *)&TxData,1,0xffff);
    return (0x00);
  }
  else
  {
    return (0x01);
  }
}


/**
  * @name   void HDL_RS485_uart_IRQ_Task(void);
  * @brief  通过485串口接收中断,每个模块1个中断,
  *               刷新接收状态和数据
  *               当为接收模式时,接收完成中断触发后,则缓存接收数据,并将缓存标志位置1,
  *               .RxBufferstate   = RX_BUF_READY,
  *               .RxBuffer        = hal串口数据,
  *         
  * @param  this_485 指针型结构体,指向TypeDef_HDL_RS485类型的结构体对象,
  *         1个485模块一个结构体,方便操作多个485模块
  * 
  * @retval 无
  *                         
  */
void HDL_RS485_uart_IRQ_Task(void)
{
  if(RS481_1_UartHandle.Instance == RS485_1.Uart_Channel)
		{
			if(__HAL_UART_GET_FLAG(&RS481_1_UartHandle, UART_FLAG_RXNE) != RESET)
			{
				if(RS485_1.mode == RX_MODE)
				{
					HAL_UART_Receive(&RS481_1_UartHandle,(uint8_t *)&RS485_1.RxBuffer,1,1000);
					RS485_1.RxBufferstate = RX_BUF_READY;
				}
			}
		} 
}

/*********************************************END OF FILE**********************/





简易说明:运用串口中断接收上位机发送的一个字节数据,运用面向对象的思想进行封装,要修改不同的串口和引脚,只需修改对应的宏定义即可

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
RS485通信模块是一种常用的串行通信接口模块,广泛应用于工业领域。它采用差分信号传输方式,具有高抗干扰能力和长距离传输特性,能够在远距离传输数据。 RS485通信模块的设计主要包括硬件设计和软件设计两个方面。 在硬件设计方面,首先需要选择合适的RS485芯片,如MAX485等。接下来,需要设计电源电路,保证模块正常工作。同时,还需要设计与外部设备连接的接口电路,包括信号电平转换、电流限制等。此外,还需要设计保护电路,以防止模块在异常情况下受到损坏。最后,进行整体电路布局和PCB设计。 在软件设计方面,首先需要编写驱动程序,实现与RS485芯片的通信控制。驱动程序要能够控制发送和接收数据,并对数据进行校验处理。其次,需要编写上层应用程序,实现对RS485模块的功能扩展,如数据读写、通信协议处理等。在设计通信协议时,一般采用一种简单易懂的格式,如MODBUS等。最后,进行综合测试和优化,确保模块稳定可靠。 总的来说,RS485通信模块设计需要考虑硬件和软件两个方面的因素。对于硬件设计,需要选择合适的芯片和电路设计,确保模块能够稳定工作。软件设计方面,需要编写驱动程序和应用程序,实现数据的发送和接收,并根据实际需求进行功能扩展。通过综合测试和优化,确保通信模块的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值