基于STM32 RS485传感器数据采集(参考正点原子部分代码)

这篇具有很好参考价值的文章主要介绍了基于STM32 RS485传感器数据采集(参考正点原子部分代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目前工业上,传感器一般都选RS485,modbus通讯协议,这种通讯方式,有很强的鲁棒性,本篇文章基于原子哥的精英板进行开发。

1、初始化与电脑通信的串口(PA9 PA10)

//初始化USART2
void RS485_Init(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOD,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
        
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;//PA2(TX)复用推挽输出
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&GPIO_InitStructure);
        GPIO_SetBits(GPIOA,GPIO_Pin_2);//默认高电平
        
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3;//PA3(RX)输入上拉
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;   //修改原GPIO_Mode_IPU(输入上拉)->GPIO_Mode_IN_FLOATING(浮空输入)/
        GPIO_Init(GPIOA,&GPIO_InitStructure);
        
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;//修改PG9(RE/DE)通用推挽输出->PD7(RE/DE)通用推挽输出//
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
        GPIO_Init(GPIOD,&GPIO_InitStructure);
        GPIO_ResetBits(GPIOD,GPIO_Pin_7);//默认接收状态
        
        USART_DeInit(USART2);//复位串口2
        USART_InitStructure.USART_BaudRate=RS485_Baudrate;
        USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
        USART_InitStructure.USART_WordLength=USART_WordLength_8b;
        USART_InitStructure.USART_StopBits=USART_StopBits_1;
        USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;//收发模式
        switch(RS485_Parity)
        {
                case 0:USART_InitStructure.USART_Parity=USART_Parity_No;break;//无校验
                case 1:USART_InitStructure.USART_Parity=USART_Parity_Odd;break;//奇校验
                case 2:USART_InitStructure.USART_Parity=USART_Parity_Even;break;//偶校验
        }
        USART_Init(USART2,&USART_InitStructure);
        
        USART_ClearITPendingBit(USART2,USART_IT_RXNE);
        USART_ITConfig(USART2,USART_IT_RXNE,ENABLE);//使能串口2接收中断
        
        NVIC_InitStructure.NVIC_IRQChannel=USART2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        
        USART_Cmd(USART2,ENABLE);//使能串口2
        RS485_TX_EN=1;//模式
        
        Timer7_Init();//定时器7初始化,用于监视空闲时间
        //Modbus_RegMap();//Modbus寄存器映射
}

2、采用串口中断将数据保存到数组buff中

void RS485_SendData(u8 *buff,u8 len)
{ 
		RS485_TX_EN=1;//切换为发送模式
		while(len--)
		{
						while(USART_GetFlagStatus(USART2,USART_FLAG_TXE)==RESET);//等待发送区为空
						USART_SendData(USART2,*(buff++));
		}
		while(USART_GetFlagStatus(USART2,USART_FLAG_TC)==RESET);//等待发送完成
		TX_RX_SET=1; //发送命令完成,定时器T4处理接收到的数据
		RS485_TX_EN=0;
}

3、用定时器来配置一帧字节是否结束(空闲时间>指定时间)

void TIM7_IRQHandler(void)
{                                                                   
    if(TIM_GetITStatus(TIM7,TIM_IT_Update)!=RESET)
    {
        TIM_ClearITPendingBit(TIM7,TIM_IT_Update);//清除中断标志
        TIM_Cmd(TIM7,DISABLE);//停止定时器
        RS485_TX_EN=1;//默认为发送模式       485模式控制.0,接收;1,发送.
        RS485_RxFlag=1;//置位帧结束标记
//        errpace=1;
    }
}


4、主机发送请求指令(从机地址、功能码 、起始地址、读取个数)

void modbus_rtu(void)
{    
    static u8 i=0;
    static u8 j=0;
    switch(i)
    {
        case 0:      //modbus执行命令第一步。
                //RS485_TX_Service();  //向从机发送一个请求。就在此时发送完成TX_RX_SET=1 发送命令完成,定时器T4处理接收到的数据
            //在此处也可以直接写Master_Service( SlaverAddr, Fuction, StartAddr, ValueOrLenth);
            //多次通讯结果可以按照类似的封装进行填写
            
            RS485_TX_Service();
               if(TX_RX_SET) i=1; //发送,接受命令切换。 0 发送模式 1 接受模式
            
        
            state=1;
                break;
        case 1:     //modbus命令执行第二步。
                RS485_RX_Service();  //执行数据接收 
            state=2;
                if(ComErr==0)  //如果什么错误都没有发生
                {
                    i=2;//完成命令更换功能码!
                } //一次通讯已经完成
                else   //错误接收后再次准备接收
                {
                    i=1;//
                    j++;//一个命令发送3次没有应答切换下一个命令
                    if(j>=2)
                    {
                        j=0;
                        i=2;
                        ComErr=7;  //通讯超时
                    }                
                }
                break;
        case 2: //从机地址++    
            i=0;
            state=3;
                break;
        case 3://功能码,这个是空余出来做报错以及其他处理的
                break;                
            
    }
    
}

5、从机响应,通过校验码判断数据是否成功

u16 CRC_Compute(u8 *puchMsg, u16 usDataLen) 
{ 
	u8 uchCRCHi = 0xFF ; 
	u8 uchCRCLo = 0xFF ; 
	u32 uIndex ; 
	while (usDataLen--) 
	{ 
		uIndex = uchCRCHi ^ *puchMsg++ ; 
		uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ; 
		uchCRCLo = auchCRCLo[uIndex] ; 
	} 
	return ((uchCRCHi<< 8)  | (uchCRCLo)) ; 
}//uint16 crc16(uint8 *puchMsg, uint16 usDataLen)

6、处理主机采集到的数据

void USART2_IRQHandler(void)//串口2中断服务程序
{
       
        u8 res;
        u8 err;
     
        if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)
        {
                if(USART_GetFlagStatus(USART2,USART_FLAG_NE|USART_FLAG_FE|USART_FLAG_PE)) {err=1;errpace=2;}//检测到噪音、帧错误或校验错误
                else err=0;
                res=USART_ReceiveData(USART2); //读接收到的字节,同时相关标志自动清除
                
                if((RS485_RX_CNT<2047)&&(err==0))
                {
                        RS485_RX_BUFF[RS485_RX_CNT]=res;
                        RS485_RX_CNT++;
                        
                        TIM_ClearITPendingBit(TIM7,TIM_IT_Update);//清除定时器溢出中断
                        TIM_SetCounter(TIM7,0);//当接收到一个新的字节,将定时器7复位为0,重新计时(相当于喂狗)
                        TIM_Cmd(TIM7,ENABLE);//开始计时
                }
        }
}

void Modbus_03_Solve(void)
{
    u8 i;
        //u8 RegNum;
        //RegNum= RS485_RX_BUFF[2]/2;//获取字节数 6---->?
        if(1)//寄存器地址+数量在范围内
        {
                for(i=0;i<20;i++)
                {
                       Master_ReadReg[StartAddr+i]= RS485_RX_BUFF[3+i*2];           /高8位
                       Master_ReadReg[StartAddr+i]= RS485_RX_BUFF[4+i*2]+(Master_ReadReg[StartAddr+i]<<8);// 低8位+高8位
                                         Master_ReadReg[i]= RS485_RX_BUFF[3+i*2]; 
                                         Master_ReadReg[i]= RS485_RX_BUFF[4+i*2]+(Master_ReadReg[i]<<8);// 低8位+高8位
                    
 
                }
            temp=Master_ReadReg[0];
         x_shock=Master_ReadReg[1];
        y_shock=Master_ReadReg[2];
        z_shock=Master_ReadReg[3];                                             
             //volback(message);
                 ComErr=0;
        }
        else
        {
            
                ComErr=3;
        }
        TX_RX_SET=0; //命令完成
}

//Modbus功能码05处理程序   ///程序已验证OK
//写单个输出开关量
void Modbus_05_Solve(void)
{
       u16 i;
       i=ValueOrLenth;
       if((i>0&&RS485_RX_BUFF[4]==0XFF&&RS485_RX_BUFF[5]==0X00)||(i==0&&RS485_RX_BUFF[4]==0X00&&RS485_RX_BUFF[5]==0X00))
       {
            ComErr=0;
            
       }
       else
       {
            ComErr=5;
       }
       TX_RX_SET=0; //命令完成       
}

//Modbus功能码06处理程序   //已验证程序OK
//写单个保持寄存器
void Modbus_06_Solve(void)
{
        u16 i; //数据返回校验用    
        i=(((u16)RS485_RX_BUFF[4])<<8)|RS485_RX_BUFF[5];//获取寄存器数量
        if(i==Master_WriteReg[StartAddr])
        {
            ComErr=0;
        }
        else
        {
            ComErr=6;
        }
        TX_RX_SET=0; //命令完成

}
//Modbus功能码15处理程序   //程序已验证OK
//写多个输出开关量
void Modbus_15_Solve(void)
{
        u16 i;//数据返回校验用
        i=(((u16)RS485_RX_BUFF[4])<<8)|RS485_RX_BUFF[5];//获取寄存器数量
         if(i==ValueOrLenth)
        {
            ComErr=0;
        }
         else
        {
            ComErr=15;
        }
        TX_RX_SET=0; //命令完成   
}

//返回温度值
u16 temperature(void)
{
    return temp;
}
 //返回x 振动
u16 X_shock(void)
{
    return x_shock;
}
    
//返回y 振动
u16 Y_shock(void)
{
    return y_shock;
}
//返回z 振动
u16 Z_shock(void)
{
    return z_shock;
}

7、结果展示

基于STM32 RS485传感器数据采集(参考正点原子部分代码)

有什么疑问或想要完整程序可私聊我 ,平时回消息都比较快文章来源地址https://www.toymoban.com/news/detail-509343.html

到了这里,关于基于STM32 RS485传感器数据采集(参考正点原子部分代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python 与 RS-485 传感器设备进行串口通信, 读取数值

    基础准备 使用的485设备 https://item.taobao.com/item.htm?spm=a1z09.2.0.0.29902e8dKQTU6did=584607646349_u=p208d7bb2e05dc ​​​ 485设备资料 📎导轨式温湿度传感器.pdf 使用的Python库 pyserial (非内置库) 将RS - 485传感器设备先转成RS-232, 然后将RS -232转成USB串口, 插入到串口, 即可使用电脑COM进行串口通

    2024年02月04日
    浏览(37)
  • STM32实现薄膜压力传感器数据采集(标准库和HAL库实现)

    单片机型号及压力传感器: STM32F103C8T6 最小系统板 压力传感器选用的是薄膜压力传感器 生活中经常遇到需要测量压力值,因此,考虑到这样的需求从网上买了一个薄膜压力传感器,实物图如下: 柔性薄膜压力传感器的 产品特点 : 超薄,厚度小于0.3mm 响应速度快 寿命长,通

    2024年02月02日
    浏览(35)
  • STM32采集问答式串口传感器数据写入SD卡(spi模式)

    STM32f103RCT6板子 问答式温湿度传感器(TTL信号) 外接SD卡模块(淘宝都差不多) 1. SD卡模块 ,采用SPI1接线 (CLK)SCK —PA5 (DATA0)MISO —PA6 (CMD)MOSI —PA7 (DATA3)CS —PA4 前面小括号里的是SDIO模式的接线,可以忽略。 2. 传感器模块 问答式TTL信号的传感器都可以, 连接到板子的串口2,

    2024年02月05日
    浏览(40)
  • TCP透传数据至Onenet平台(简单用STM32上传采集的传感器数据)

    主页点击控制台  点击全部产品服务,再点击多协议接入  选择TCP透传,点击添加产品      点击确定,然后选择立即添加设备  点击添加设备  随便起个设备名称,这里的鉴权信息等下要用来作为登录设备用,点击添加  添加数据流模板,就是绑定上传的数据      这里我

    2024年02月05日
    浏览(34)
  • Note10:基于STM32H7+HAL+CubeMX+DMA+SPI+串口中断+定时器+RTC的多传感器数据采集系统(2*ADXL355和ADXL375通过Sync时序同步)

    本文的初衷一方面是将我的一些关于STM32开发方面浅显的个人经验分享给初学者、并期望得到大佬的批评指正,另一方面是记录自己的实验过程便于回顾。 我预感应该要写很多,不过鉴于之前的数篇笔迹中,对于SPI/DMA/ADXL3XX系列加表的使用已经详细描述过了,所以这篇博客只

    2024年02月10日
    浏览(44)
  • 搬运机器人RFID传感器CNS-RFID-01|1S的RS485(MODBUS|HS协议)通讯连接方法

    搬运机器人RFID传感器CNS-RFID-01|1S支持RS485通信,可支持RS485(MODBUS RTU)协议、RS485-HS协议,广泛应用于物流仓储,立库 AGV|无人叉车|搬送机器人等领域,常用定位、驻车等,本篇重点介绍CNS-RFID-01|1S RFID传感器的RS485通信连接方法。 CNS-RFID-01|1S RFID传感器 1、RS485连接方法 用线缆

    2024年02月04日
    浏览(43)
  • 基于STM32的土壤湿度传感器使用

    最近在学习中用到了ADC数据采集这里使用的硬件模块为土壤湿度传感器,下面为土壤传感器相关的使用方法和代码介绍。 1、土壤湿度传感器实物图 土壤湿度传感器一共有4个引脚分别为: GND VCC DO AO,在本次实验中使用的为A0模拟引脚,因此在单片机资源上需要使用到ADC,模

    2024年02月12日
    浏览(30)
  • 基于STM32的双轴XY摇杆传感器模块使用

    本文主要介绍的是如何通过STM32核心板 控制 双轴XY摇杆传感器模块 以及将传感信息打印到串口调试助手 提示:以下是本篇文章正文内容,下面案例可供参考 外形如图所示,共五个引脚 分别是VCC GND X轴传感模拟量输出 以及 Y轴传感模拟量输出 以及一个SW按键数字量输出 摇杆

    2024年02月03日
    浏览(33)
  • SPI传感器接口设计与优化:基于STM32的实践

    SPI(串行外设接口)是一种常用的串行通信协议,用于在微控制器和外部设备之间进行全双工的高速数据传输。 在本文中,我们将探讨如何基于STM32微控制器设计和优化SPI传感器接口,并提供相应的代码示例。 1. SPI传感器接口设计 SPI传感器接口设计的主要目标是实现可靠、

    2024年01月19日
    浏览(30)
  • 基于STM32_DS18B20单总线传感器驱动

    本文以一款典型的单总线传感器及其驱动——DS18B20为例,简单对1-Wire总线接口的传感器做个示例讲解,该项目基于硬件平台STM32F407,使用标准库本完成。 DS18B20数字温度计提供9至12位(可配置)温度读数,指示设备的温度。信息通过1-Wire总线接口发送到/从DS18B20,因此只需要从中

    2024年02月07日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包