搜索
bottom↓
回复: 4

我的MODBUS通讯协议程序:为什么可以读取51个数据,却不能预置51个数据?

[复制链接]

出0入0汤圆

发表于 2008-7-15 18:22:47 | 显示全部楼层 |阅读模式
我采用ATMEAL 128单片机
 (1)、定时中断时间间隔=10MS
  (2)、串口接收采用中断方式
  (3)、串口发送采用中断方式
 (4)、MODBUS分析程序在主程序中执行
  (5)、每次读51个INT数据
 (6)、每次写51个INT数据
 以下是读取保持寄存器(功能码=03)和预置多个寄存器(功能码=16)程序片段
 为什么:
    (1)通过上位机可以每次都正确读取到51个整数数据,
    (2)而通过上位机预置51个数据给单片机时,上位机基本上收不到单片机的《应答信号》
        我感觉好象是定时中断将下面一段代码打断,导致单片机CRC校验无法通过,使得上位机无法收到预置多个寄存器的应答信号
           case 16: //预置多个寄存器  
               tempData = (USART1_mscomm_buffer[4]<<8) + USART1_mscomm_buffer[5];  
               tempData = tempData * 2;  
               tempData += 9;  
               if (USART1_receCount >= tempData)
           {
                            ....
                          if (crcData == (USART1_mscomm_buffer[tempData-2]<<8)+ USART1_mscomm_buffer[tempData-1])
                      }     //校验通不过

    (3)如果将定时中断服务程序中的代码全部屏蔽,则通过上位机预置51个数据给单片机时,上位机可以收到单片机的正确应答信号
        难道是中断服务程序执行时间过长吗?
        我的定时中断间隔=10ms,中断服务程序大约执行3.2ms
    (4)我测试过跟置数间隔没有关系,我将上位PC机定时中断设置为每隔1秒预置一次数据,还是收不到应答。

void USART1_Modbus_Analyze(void)
{
 unsigned int crcData;
 unsigned int tempData;
         
 if (USART1_receCount > 5)
 {
   switch (USART1_mscomm_buffer[1])
   {
        case 3: //读取保持寄存器
          if (USART1_receCount >= 8)
          {
                UCSR1B &= ~BIT(7);
                if (USART1_mscomm_buffer[0] == module_addr)//比较从设备地址
                {
                  crcData = CRC16(USART1_mscomm_buffer,6);
                  if (crcData == (USART1_mscomm_buffer[6]<<8) + USART1_mscomm_buffer[7])
                        USART1_ReadRegisters();
                }
                USART1_receCount = 0;
                USART1_checkoutError = 0;
                UCSR1B |= BIT(7);
          }
          break;
        case 16: //预置多个寄存器
          tempData = (USART1_mscomm_buffer[4]<<8) + USART1_mscomm_buffer[5];
          tempData = tempData * 2;
          tempData += 9;
          if (USART1_receCount >= tempData)
          {
                UCSR1B &= ~BIT(7);
                if (USART1_mscomm_buffer[0] == module_addr))//比较从设备地址
                {
                  crcData = CRC16(USART1_mscomm_buffer,tempData-2);
                  if (crcData == (USART1_mscomm_buffer[tempData-2]<<8)+ USART1_mscomm_buffer[tempData-1])
                        USART1_PresetMultipleRegisters();
                }
                USART1_receCount = 0;
                USART1_checkoutError = 0;
                UCSR1B |= BIT(7);
          }
          break;
        }
  }
}


void main(void)
{
     //初始化省略

  while (1)
 {
        USART1_Time_Proc();//超时处理
        USART1_Modbus_Analyze();//MODBUS分析程序
 }
}

出0入296汤圆

发表于 2008-7-17 16:15:33 | 显示全部楼层
你在定时器中断处理程序的一开始加入SEI(),试试看……

出0入0汤圆

 楼主| 发表于 2008-8-18 14:02:18 | 显示全部楼层
我不希望USART中断打断定时中断,
  我的解决方案:
    将定时中断中,与时间无关的程序代码移到主程序中执行。定时中断尽可能的短小精悍。

出0入0汤圆

发表于 2008-8-19 08:36:26 | 显示全部楼层
http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=887775&bbs_page_no=1&search_mode=3&search_text=lcqqcl&bbs_id=9999

这是我根据论坛上的前辈的贴子修改的
调试通过了,希望能对你有帮助

出0入0汤圆

 楼主| 发表于 2008-8-27 10:17:59 | 显示全部楼层
【3楼】 lcqqcl,谢谢。
  你使用功能码16(预置多个寄存器),试没有试过,上位机一次给单片机预置120个数据(大约120*2+9=249)
    分别在1200,2400,4800,9600,11400待波特率下通讯都畅通吗?
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-8 12:54

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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