找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1599|回复: 4
收起左侧

CC2530采集485型modbus传感器数据,代码如下,功能无法实现,希望大家进行指点,bu...

[复制链接]
ID:841786 发表于 2022-7-30 16:03 | 显示全部楼层 |阅读模式
#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);  //串口接收监控
}


回复

使用道具 举报

ID:401564 发表于 2022-7-30 18:07 | 显示全部楼层
你这延时,看着都别扭,用得着5个for吗?485是要先操作DE和RE来确定为接收还是发送模式的
485可以连续发送多个字节,可以用数组发送
这是我的485发送程序,你参考一下
Delay10us:10uS延时函数
Send_Out_Byte:串口发送一个字节函数,根据不同单片机,自己写
void Send_Rs485(unsigned char *buf,unsigned char len)//RS485发送数据,待发送数据指针buf,数据长度len
{
        RE=1;                                        //RS485设定为发送状态
        Delay10us(5);                         //此处要加延时,让MAX485有反应的时间
        do
        {                               
                Send_Out_Byte(*buf);//通过串口发送到485总线
                buf++;
        }
        while(len--);
        Delay10us(5);                        //延时
        RE=0;                                        //RS485设定为接收状态
}

回复

使用道具 举报

ID:920086 发表于 2025-5-9 16:37 | 显示全部楼层
解决了吗吧主
回复

使用道具 举报

ID:920086 发表于 2025-5-10 09:00 | 显示全部楼层
有结果了吗
回复

使用道具 举报

ID:940483 发表于 2025-5-13 14:26 | 显示全部楼层
我看你这个“01 03 02 00 00 03 04 73”   buf数组初始化为8bit,可len没初始化。”UartWrite(buf, len)“ len的值为0,导致发送错误。len应置8,因为buf数组有八个元素。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表