搜索
bottom↓
回复: 4

avr16的单片机modbus通讯不上求帮助

[复制链接]

出0入0汤圆

发表于 2013-3-25 14:57:28 | 显示全部楼层 |阅读模式
//************************************************************//
//**************开关量的采集修改******************************//
//*************2013.3.12**********路************************//
//************宏定义文件 ************************************//
//***********************************************************//
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#define         F_CPU        11059200                   /* 单片机主频为11.0592MHz,用于延时子程序 */
#include <util/delay.h>       
#include <avr/iom16.h>                       
#define  uchar unsigned char
#define  uint unsigned int
#define  ulong unsigned long int
#define  CON1(x) if(x==0){PORTD&=~_BV(PD2);}else{PORTD|=_BV(PD2);} //485通信1接受发送使能
#define  baud           9600                                       //设置波特率的大小
#define  baud_setting   (uint)((ulong)F_CPU/(16*(ulong)baud)-1)    //波特率计算公式
#define  baud_h         (uchar)(baud_setting>>8)                   //提取高位
#define  baud_l         (uchar)(baud_setting)                      //低位
#define  delay_us(x)     _delay_us(x)    //AVR GCC延时函数 x(us)
#define  delay_ms(x)     _delay_ms(x)    //AVR GCC延时函数 x(ms)


//*************************************************************
//*** 全局变量定义 ***0
//*************************************************************                    
uchar RX1_data[125];           
uchar RX1_arm_data[125];         
uchar RX1_Len;
uchar ddada[50]= { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //接收的数据
                               0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uchar addr_arm;          //报警地址
uchar temper[50]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //处理的数据
                               0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                                   0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};   


uchar  RX1_state;        //数据处理完标志位
uchar  RX1_len;          //串口1计数据长度
uchar  RX1_Cmd_ok;       //串口1接收完成标志位
uchar  dz,H_dz,L_dz,ml;  //从站发送地址,地址高位,地址低位,功能码
uint   H_nu,L_nu,nu;     //接收数量高位,接收数量低位,接收数量
uchar  ml;               //功能码
uchar  ms2;              //定时中断2的时间变量
//#define uchar unsigned char
//#define uint unsigned int
//#define ulong unsigned long int

/* CRC 高位字节值表 */
const prog_char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
0x40
};

/* CRC低位字节值表*/

const prog_char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
0x40
};

/***********************************/
//函数名称:CRC16(uchar *pushMsg,uchar usDataLen)
//函数功能:CRC校验函数
//输入参数:*pushMsg          校验数据起始地址指针
//输出参数:usDataLen     校验数据长度
//返 回 值:16位CRC校验码
/***********************************/
uint CRC16(uchar *pushMsg,uchar usDataLen)
{
   uchar uchCRCHi=0xFF;           /*高CRC字节初始化*/
   uchar uchCRCLo=0xFF;           /*低CRC 字节初始化*/
   uint uIndex;                   /*CRC循环中的索引*/
   
   while (usDataLen--)            /*传输消息缓冲区*/
   {
        uIndex   = uchCRCHi ^ *pushMsg++; /* 计算CRC */
                uchCRCHi = uchCRCLo ^ pgm_read_byte(&auchCRCHi[uIndex]);
                uchCRCLo = pgm_read_byte(&auchCRCLo[uIndex]);
   }
   return (uchCRCHi<< 8 | uchCRCLo);
}


//*********************************************/
//函数名称:port_init
//函数功能:IO端口初始化
//输入参数:无
//输出参数:无
//返 回 值:无
/*********************************************/
void port_init(void)
{
        PORTA = 0xFF;    //全为0,全输出低电平输入:
    DDRA  = 0x00;  
    PORTB = 0xFF;
    DDRB  = 0x00;    //全为0,全输出低电平输入:
  
}
/*********************************************/
//函数名称:usart1_init
//函数功能:串口通信初始化程序
//输入参数:无
//输出参数:无
//返 回 值:无
/*********************************************/

void usart1_init(void)
{
  UCSRA = 0x00;                              //工作在异步正常模式下 U2X=0
  UCSRB = 0xF8;                             //接收中断和发送中断允许
  UCSRC=(1<<UCSZ1)|(1<<UCSZ0);            //写UCSRC寄存器,异步通信无校验,8位数据1位停止位
  UBRRH=baud_h;                            //写波特率的值
  UBRRL=baud_l;
}

/***********************************/
//函数名称:ADC_read
//函数功能:模数转换
//输入参数:无
//输出参数:
//返 回 值:
/***********************************/
uchar bomakaiguan(void)
  {  
     uchar j,i;
     
         j=~PINB;
         i=j&0xff;
             
          return i;  
  }
/***********************************/
//函数名称:ADC_read
//函数功能:模数转换
//输入参数:无
//输出参数:
//返 回 值:
/***********************************/
uchar press_key(void)
  {  
     uchar j,i;
     
         j=~PINA;
         i=j&0xff;
             
          return i;
  }

/*********************************************/
//函数名称:timer2_init(void)
//函数功能:定时T2初始化配置函数  1ms
//输入参数:无
//输出参数:无
//返 回 值:无
/*********************************************/
void timer2_init(void)
{

TCCR2 = 0x00;   //stop
ASSR  = 0x00;   //set async mode
TCNT2 = 0xF6;   //定时为1ms 定时器初值,定时器加一计数
TCCR2 = 0x07;   //普通模式,OC0不输出,1024分频
TIFR  = 0x40;   //清中断标志位
TIMSK = 0x40;   //溢出中断使能

}

/*********************************************/
//函数名称:SIGNAL(SIG_OVERFLOW2)  3.5T要做的事。
//函数功能:T2溢出中断服务程序
//输入参数:无
//输出参数:无
//返 回 值:无
/*********************************************/
SIGNAL(SIG_OVERFLOW2)
{
       
        TCNT2=0xF6;     //定时器赋初值,非自动重装模式
       
        if(ms2<15)
        {
            ms2++;      //微秒
        }
        else
        {
            TCCR2  = 0x00;               //停止定时器
    //        RX1_arm_len=RX1_Len;         //命令长度
                RX1_Len=0;
            RX1_Cmd_ok=1;                 //一个消息接收完成!等待处理
        }
}
/***********************************/
//函数名称:SIGNAL(SIG_USART1_RECV)
//函数功能:串口接受中断处理函数,接收串口数据。
//输入参数:无
//输出参数:接收的串口数据
//返 回 值:无
/***********************************/

SIGNAL(SIG_USART_RECV)
{
   

           TCCR2=0x00;         //停止计数


            if(ms2>15)
            {   
           RX1_len=0;

           ms2=0;

         }

             
                RX1_data[RX1_Len]=UDR;     //接收数据1
                        
                 RX1_Len++;
                  
                   // RX1_len&=0xFF;          //最大接收的字节32个
   
          
               
                 ms2=0;

        TCCR2=0x00;   //停止定时器
        TCNT2=0xF6;   //定时为1ms 定时器初值,定时器加一计数
                TIMSK=0x40;   //溢出中断使能
                TCCR2=0x07;   //普通模式,OC0不输出,1024分频
              


}
/***********************************/
//函数名称:usart1_TX
//函数功能:串数据发送查询方式发送*
//输入参数:tx_data
//输出参数:串口数据
//返 回 值:无
/***********************************/

void usart1_TX(uchar tx_data)
{  

  while(!(UCSRA &(1<<UDRE)));   
  UDR = tx_data;                 
  
}
//*********************************************/
//函数名称:串口ViewTem_cmd 发送数据   取采集的开关变量
//函数功能:
//返 回 值:无
/*********************************************/
void ViewTem_cmd(void)  
{
        uint crc,i,j;

    uchar fs[100];
    ddada[0]=press_key();
                            
        CON1(0);
        fs[0]=temper[0];                          //从机地址                          
        fs[1]=temper[1];                          //命令号                        
        fs[2]=temper[2];                         //数据字节数
                           
    for(i=0;i<temper[2];i++)
       
         {
           fs[3+i] =ddada[i];
          
         
         }
       

       
        crc=CRC16(&fs[0],3+temper[2]);   
       
        fs[3+temper[2]]=crc>>8;
        fs[4+temper[2]]=crc&0xff;

        wdt_reset();//喂狗
       
       
       
        for(j=0;j<5+temper[2];j++)
       
        usart1_TX(fs[j]);
       
        while(!(UCSRA & (1<<UDRE)));
       
        _delay_ms(2);

    CON1(1);

             

}
/***********************************/
//函数名称:deal_RX1data
//函数功能:串口1数据中断处理函数,处理接收的串口1数据。
//输入参数:无
//输出参数:接收的串口数据
//返 回 值:正确与否的标志
/***********************************/

void deal_RX1data(void)

{
    uchar  j;
        uint   crc;       //本地计算CRC
        uint   js_crc;    //接收到的CRC
        uint   n;   
        

       
        if(RX1_Cmd_ok==1)
        {
              for(j=0;j<8;j++)
                    {
                       
                           RX1_arm_data[j]=RX1_data[j];  //转存串口接收的数据,等待处理!
                       
                        }
                  dz= RX1_arm_data[0];       //取数据来源地址
                  ml= RX1_arm_data[1];       //取命令码
                H_dz= RX1_arm_data[2];       //地址高位
                L_dz= RX1_arm_data[3];       //地址低位
                H_nu= RX1_arm_data[4];       //数据高位
        L_nu= RX1_arm_data[5];       //数据低位
                  nu=((H_nu<<8)|L_nu);       //总数据
                  if(dz==bomakaiguan())
                 {
                             if(ml==0x02)   //命令
                          
                                  {
                                         wdt_reset();//喂狗
       
                                                                    
                                        crc=CRC16(&RX1_arm_data[0],6);      //计算接收命令CRC
                                        js_crc= RX1_arm_data[6];                //接收到的CRC
                                        js_crc=((js_crc<<8)| RX1_arm_data[7]);
                                                                
                                                                                
                                         wdt_reset();//喂狗

                                       if(crc==js_crc)
                                 
                                             
                                         {      
                                                     _delay_ms(100);
                                                                                                                                                                 
                                                   temper[0]=RX1_arm_data[0];

                                                         temper[1]=RX1_arm_data[1];
                                                             
                                                                 n=nu/8;
                                 
                         if(n*8<nu)

                                                               n=n+1;
                                 
                                                          temper[2]=n;

                                                          ddada[0]=press_key();
                          
                                                          _delay_ms(100);                                                                                                                                                      
                                                                                                     
                                           ViewTem_cmd();
                                       
                                                  }
                                    
                }                                                                                                                                                                                                                                                                                               
         
        }
               
          RX1_Cmd_ok=0;       
          
          }       

}

/*********************************************/
//函数名称:初始化子程序
//函数功能:包含所有的初始化程序
//输入参数:无
//输出参数:无
//返 回 值:无
/*********************************************/
void init_devices(void)
{
       
         cli(); //禁止所有中断
       
        port_init();
       
        usart1_init();
   
        timer2_init();

        sei();//开全局中断
       
}

/*********************************************/
//函数名称:主函数
//函数功能:包含所有的初始化程序
//输入参数:无
//输出参数:无
//返 回 值:无
/*********************************************/

int main(void)
{   

     init_devices();
                       
     _delay_ms(300);        

       
        while(1)
       
   {         
            wdt_reset();//喂狗
          
            _delay_ms(300);
                                  
        deal_RX1data() ;//接收命令
                    
   }                         
                       
                 
                 
     
}

出0入0汤圆

发表于 2013-3-27 19:23:44 | 显示全部楼层
怎么会通讯不上呢,具体原因是什么,你可能程序还没搞懂,先学吧!

出0入0汤圆

发表于 2017-2-10 21:42:21 | 显示全部楼层
好了没?前辈。能分享一下通信成功的源码吗?

出0入0汤圆

 楼主| 发表于 2017-2-11 10:13:00 | 显示全部楼层
pillar2060 发表于 2017-2-10 21:42
好了没?前辈。能分享一下通信成功的源码吗?

时间太长了,这个代码应该能通信上, 源码都不知道拿去了!

出0入0汤圆

发表于 2017-2-13 10:22:08 | 显示全部楼层
jiangzhimin 发表于 2017-2-11 10:13
时间太长了,这个代码应该能通信上, 源码都不知道拿去了!

奥,谢谢!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-5-10 18:26

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

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