以梦喂码 2022-07-30 15:57 采纳率: 0%
浏览 140
已结题

单片机采集485型传感器数据

最近做一个项目,展很慢,希望大家可以帮忙指点指点。项目:由 CC2530板子对一个485型modbus传感器进行数据采集,代码如下,希望可以得到指点
#include <iocc2530.h>
#include <string.h>
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
#define rs485_de P1_7
#define rs485_re P1_5
//延时啊
void delay(unsigned int t,unsigned int u)
{
        unsigned int i,j;
        for(i=0;i<t;i++)
        for(j=0;j<u;j++);
}

//延时
void Delay(uint n)
{
uint i;
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
for(i = 0;i<n;i++);
}

void Init485_Port()
{
  //初始化RS485  
  P1SEL &= ~0xA0;            //P1-7作 P1-5为通用I/O口
  P1DIR |= 0xA0;             
}

void Init485_send()    //传感器发送数据  
{
  Init485_Port();
  rs485_de =0;
  rs485_re =0;
}
void Init485_rec()    //传感器发接收数据 
{
  Init485_Port();
  rs485_de =1;
  rs485_re =1;
}
/* 485通信 */
unsigned char len;
unsigned char buf[40]={0x01,0x03,0x00,0x00,0x00,0x02,0xC4,0x0B};  //读取读取叶面温湿度设备(地址 0x01)的温湿度值
int flagFrame = 0;  //帧接收完成标志,即接收到一帧新数据
int flagTxd = 0; //单字节发送完成标志,用来替代 TXD 中断标志位
unsigned char cntRxd = 0;   //接收字节计数器
unsigned char  bufRxd[64];  //接收字节缓冲区

unsigned char TORH=0;//定时器中用到
unsigned char TORL=0;

unsigned int wendu_H=0x00;                 //温度值高4位字节
unsigned int wendu_L=0x00;                 //温度值低4位字节
unsigned int shidu_H=0x00;                 //湿度值高4位字节
unsigned int shidu_L=0x00;                 //湿度值低4位字节


/* 串口配置函数,baud-通信波特率 */
void initUART0(void)
{
  CLKCONCMD &= ~0x40;                           //设置系统时钟源为32MHZ晶振
  while(CLKCONSTA & 0x40);                      //等待晶振稳定
  CLKCONCMD &= ~0x47;                           //设置系统主时钟频率为32MHZ
  
  PERCFG = 0x00;                      //位置1 P0口
  P0SEL = 0x3c;                  //P0用作串口
  P2DIR &= ~0XC0;                               //P0优先作为UART0    
  
  U0CSR |= 0x80;                  //串口设置为UART方式
  U0GCR |= 7;                
  U0BAUD |= 59;                  //波特率设为4800
//中断设置可能需要修改
  UTX0IF = 1; //UART0 TX 中断标志初始置位 1
  U0CSR |= 0X40; //允许接收
  IEN0 |= 0x84; //开总中断,接收中断
}

/* 串口数据写入,即串口发送函数,buf-待发送数据的指针,len-指定的发送长度 */
void UartWrite(unsigned char *buf, unsigned char len)
{
        Init485_rec();
    while (len--)  //循环发送所有字节
    {
        flagTxd = 0;       //清零发送标志
        U0DBUF = *buf++;     //发送一个字节数据
        while (!flagTxd); //等待该字节发送完成
    }
        Delay(500);
        Init485_send();
}

/* 串口数据读取函数,buf-接收指针,len-指定的读取长度,返回值-实际读到的长度 */
unsigned char UartRead(unsigned char *buf, unsigned char len)
{
    unsigned char i;
     
    if (len > cntRxd)  //指定读取长度大于实际接收到的数据长度时,
   {                     //读取长度设置为实际接收到的数据长度
       len = cntRxd;
   }
   for (i=0; i<len; i++)  //拷贝接收到的数据到接收指针上
   {
       *buf++ = bufRxd[i];
   }
   cntRxd = 0;  //接收计数器清零
   return len;  //返回实际读取长度
}


/* 串口接收监控,由空闲时间判定帧结束,需在定时中断中调用,ms-定时间隔 */
void UartRxMonitor(unsigned char ms)
{
    static unsigned char cntbkp = 0;
    static unsigned char idletmr = 0;

    if (cntRxd > 0)  //接收计数器大于零时,监控总线空闲时间
    {
        if (cntbkp != cntRxd)  //接收计数器改变,即刚接收到数据时,清零空闲计时
        {
            cntbkp = cntRxd;
            idletmr = 0;
        }
        else                      //接收计数器未改变,即总线空闲时,累积空闲时间
        {
            if (idletmr < 30) //空闲计时小于 30ms 时,持续累加
            {
                idletmr += ms;
                if (idletmr >= 30) //空闲时间达到 30ms 时,即判定为一帧接收完毕
                {
                    flagFrame = 1;  //设置帧接收完成标志
                }
            }
        }
    }
    else
    {
        cntbkp = 0;
    }
}

/****************************************************************
                     中断处理函数
****************************************************************/
#pragma vector = URX0_VECTOR
__interrupt void UART0_ISR(void)
{
 if (URX0IF)  //接收到新字节
    {
        URX0IF = 0;  //清零接收中断标志位
        if (cntRxd < sizeof(bufRxd)) //接收缓冲区尚未用完时,
        {                                
          //保存接收字节,并递增计数器
            bufRxd[cntRxd++] = U0DBUF;
        }
    }
    if (UTX0IF)  //字节发送完毕
    {
        UTX0IF = 0;   //清零发送中断标志位
        flagTxd = 1;  //设置字节发送完成标志
    }
   
}

/****************************************************************
                     定时器
****************************************************************/
void ConfigTimer0(unsigned int ms)
{
    unsigned long tmp;
        tmp=16000000/12;          //12M晶振
        tmp=(tmp*ms)/1000;
        tmp=65536-tmp;
        tmp=tmp+33;
        T1CTL = 0x0d;
        TORH=(unsigned char)(tmp>>8);
        TORL=(unsigned char)tmp;
        T1CC0L=TORL;
        T1CC0H=TORL;
        T1IE=1;
        T1OVFIM=1;
        EA=1;
        T1CTL|=0x03;
}

void main()
{
ConfigTimer0(1);
initUART0();         //设置波特率2400
delay(200,500);
UartWrite(buf,len);         //向传感器发送命令,01 03 02 00 00 03 04 73
if (flagFrame) //有命令到达时,读取处理该命令
    {
       flagFrame = 0;
       len = UartRead(buf, sizeof(buf));  //将接收到的命令读取到缓冲区中
        }
shidu_H=bufRxd[3];                //数据帧第3字节是温度值高位,
shidu_L=bufRxd[4];                //数据帧第4字节是温度值低位。
wendu_H=bufRxd[5];                //数据帧第4字节是温度值高位,
wendu_L=bufRxd[6];                //数据帧第5字节是温度值低位。
}
/****************************************************************
                     定时器中断
****************************************************************/
#pragma vector = T1_VECTOR
__interrupt void T1_INT(void)
{
        T1CC0L=TORL;
        T1CC0H=TORH;
        UartRxMonitor(1);  //串口接收监控
}



运行后没有效果,前期进行过485通讯测试,硬件正常可正常收发
希望能得到代码上的指导,可以实现设备的温湿度采集
  • 写回答

2条回答 默认 最新

  • ___NULL___ 2022-07-30 16:45
    关注
    获得1.80元问题酬金

    你先找一个USB转485,并到现在的485线上监控数据。
    采集过程中:

    1. 如果是485什么数据也没收到:
      找个USB转TTL,RX接到单片机的TX引脚看有无数据
      1.1 如果是TX有数据,485没数据,先检查75行这个Init485_rec()有没有正确执行,如果电平切换正常的话就考虑485芯片的问题了。
      1.2 如果TX没数据,检查串口初始化以及发送函数是否正确,我没写过CC2530的代码,你自己找相关例程比对即可。
    2. 如果是485收到了数据:
      2.1 如果是只有单片机发送的数据,传感器没有响应,检查AB线是否接对了,没错的话用USB转485查询传感器检查是否ok
      2.2 如果是单片机的查询和传感器的响应都有,但是代码里收不到数据,把82行,delay的时间改小点,10ms或者100ms试试

    你的现象描述的太简单了,所以我把可能的情况都列出来了,按上面的顺序排查即可(如果你确认硬件接线等没有问题,可以先把2.2这个改了试试)。

    评论

报告相同问题?

问题事件

  • 系统已结题 8月7日
  • 修改了问题 7月30日
  • 创建了问题 7月30日

悬赏问题

  • ¥15 Opencv(C++)异常
  • ¥15 VScode上配置C语言环境
  • ¥15 汇编语言没有主程序吗?
  • ¥15 这个函数为什么会爆内存
  • ¥15 无法装系统,grub成了顽固拦路虎
  • ¥15 springboot aop 应用启动异常
  • ¥15 matlab有关债券凸性久期的代码
  • ¥15 lvgl v8.2定时器提前到来
  • ¥15 qtcp 发送数据时偶尔会遇到发送数据失败?用的MSVC编译器(标签-qt|关键词-tcp)
  • ¥15 cam_lidar_calibration报错