ba_wang_mao 发表于 2008-7-15 18:22:47

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

我采用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<<8) + USART1_mscomm_buffer;
             tempData = tempData * 2;
             tempData += 9;
             if (USART1_receCount >= tempData)
           {
                            ....
                          if (crcData == (USART1_mscomm_buffer<<8)+ USART1_mscomm_buffer)
                      }   //校验通不过

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


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

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

Gorgon_Meducer 发表于 2008-7-17 16:15:33

你在定时器中断处理程序的一开始加入SEI(),试试看……

ba_wang_mao 发表于 2008-8-18 14:02:18

我不希望USART中断打断定时中断,
  我的解决方案:
    将定时中断中,与时间无关的程序代码移到主程序中执行。定时中断尽可能的短小精悍。

lcqqcl 发表于 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

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

ba_wang_mao 发表于 2008-8-27 10:17:59

【3楼】 lcqqcl,谢谢。
  你使用功能码16(预置多个寄存器),试没有试过,上位机一次给单片机预置120个数据(大约120*2+9=249)
    分别在1200,2400,4800,9600,11400待波特率下通讯都畅通吗?
页: [1]
查看完整版本: 我的MODBUS通讯协议程序:为什么可以读取51个数据,却不能预置51个数据?