×
单片机 > 单片机程序设计 > 详情

Atmega16中使用modbus协议

发布时间:2020-06-16 发布时间:
|

调试工具:Modbus Poll


编程软件:Atmel Studio 7


理解:PC中的Modbus Poll是主机,而AVR芯片作为从机


此处有两种串行传输模式:RTU和ASCII


此处使用了RTU模式,这种模式的主要优点是较高的数据密度,在相同的波特率下比ASCII 模式有更高的吞吐率。每个报文必须以连续的字符流传送。


//以下是必要的函数


void usart_init(uint baud)//波特率


{


UCSRA = 0X00;


UCSRB = 0X00;                                 


UCSRC = 0X86;// 访问UCSRC  异步  奇偶禁止 停止位1位  字符8位


baud = fosk/16/baud-1;//得到UBRR   


UBRRL=baud;


UBRRH=baud>>8;  


UCSRB=(1<


SREG|=(1<<7);//全局中断开放


DDRD|=(1<<1);//PD1  TXD配置为输出模式


}


void usart_send(uchar *buf,uchar len)


{


while(len--)//发送所有字节


{                                //等待发送缓冲器为空


while(!(UCSRA&((1<


UDR=*buf++;//发送一个字节数据


}


}


uchar usart_read(uchar *buf, uchar len)


{


   uchar i;


   

   if (len > cntRxd)  //指定读取长度大于实际接收到的数据长度时,

   

{                  //读取长度设置为实际接收到的数据长度


   len = cntRxd;


   }


   for (i=0; i


   {


   *buf++ = bufRxd[i];


   }


   cntRxd = 0;  //接收计数器清零


   


   return len;  //返回实际读取长度


}


void UartRxMonitor(uchar ms)//定时器1发生一次中断则进入一次该函数(记得放入定时器的中断函数)


{


static uchar cntbkp = 0;


static uchar idletmr = 0;


if (cntRxd > 0)  //usart中断发生后,接收到数据,接收计数器大于零时,监控总线空闲时间


{


if (cntbkp != cntRxd)  //接收计数器改变,即刚接收到数据时,清零空闲计时


{


cntbkp = cntRxd;


idletmr = 0;//清空空闲计时


}


else                   //接收计数器未改变,即总线空闲时,累积空闲时间


{


if (idletmr < 22)  //1/19200*3.5*10


{                  


idletmr += ms;


if (idletmr >= 22)  //判定一帧接收完毕


{


flagFrame = 1;  //设置帧接收完成标志


}


}


}


}


else


{


cntbkp = 0;


}


}


void usart_driver()//此函数放入while(1)中(该函数网上有)


{


关键点需要按照自己的写,记得收和发都需要经过CRC校验(网上有现成程序crc16.c);


Modbus poll一发指令,就会触发ISR (USART_RXC_vect)函数,把指令放入bufRxd[];


等到flagFrame=1,启动usart_read()函数,把指令读到AVR;


把AVR采样得到的数放入数组,发指令的时候;


 比如:发指令 01 04   00 00   00 01   31 CA   // 设备地址01 功能码04  寄存器地址0  读取1个


 响应就是 01 04  02  00 0E  38 F4    //设备地址01 功能码04 字节数2   高字节00  低字节0E


                                                  //采样数值数码管显示为14,对应了0X0E                                


AVR采样得到的数值发回给PC机,并在Modbus poll上显示出来;


}


ISR (USART_RXC_vect)


{


if (cntRxd < sizeof(bufRxd)) //接收缓冲区尚未用完      bufRxd[]是char类型    


{                           


bufRxd[cntRxd++] = UDR;


}


}


关键字:Atmega16中  modbus协议


『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
stm32 总线矩阵介绍