|
这段时间研究了一下modbus,试着编了一段程序,如下:
M8,8MHz时钟
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <util/crc16.h>
#include <avr/wdt.h>
#define DELAY_TIME 0x82 //modbus T3.5=4ms
#define BAUD 51 // 8M 9600
#define Timer0_stop TCCR0 = 0x00 // timer0 stop
#define Timer0_star TCCR0 = 0x04 //256分频 timer0 start
#define ADDR 0x01 //本机地址
#define MAX_REC_BYTE 10 //最大数据量
#define MAX_SEND_BYTE 30
uint16_t data[]={1,2,3,4,5,6,7,9,12,56,43,67,87,90};
char rec_data[MAX_REC_BYTE]; //接收数据区
char send_data[MAX_SEND_BYTE]={ADDR}; //发送数据区
volatile uint8_t rec_counter; //接收字符计数
volatile uint8_t rec_complete; //接收完毕
uint8_t send_counter; //发送字符数
int getcrc16(char data[],uint8_t counter)
{
int crc16=0xffff;
unsigned char i;
for(i=0;i<counter;i++)
crc16=_crc16_update(crc16,data);
return crc16;
}
void Modbus_Function_1(void){};
void Modbus_Function_3(void)
{
uint8_t i;
char *pointer;
send_counter=2*rec_data[5]+3;
send_data[2]=send_counter-3;
pointer=&data[0];
for(i=0;i<2*rec_data[5];i++)send_data[3+i]=*(2*rec_data[3]+pointer++);
}
void Modbus_Function_5(void){};
void Modbus_Function_2(void){};
void Modbus_Function_16(void){};
void USART_Init( unsigned int baud )
{
/* 设置波特率*/
UBRRH = (unsigned char)(baud>>8);
UBRRL = (unsigned char)baud;
/* 接收器与发送器使能 接收中断使能 */
UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
/* 设置帧格式: 8 个数据位, 2 个停止位*/
UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0);
}
void USART_Transmit( unsigned char data )
{
/* 等待发送缓冲器为空 */
while ( !( UCSRA & (1<<UDRE)) )
;
/* 将数据放入缓冲器,发送数据 */
UDR = data;
}
ISR(USART_RXC_vect )/* 串口接收 中断程序 */
{
TCNT0 = DELAY_TIME;
Timer0_star;
rec_data[rec_counter]=UDR;
if(rec_counter<MAX_REC_BYTE-1)rec_counter++;
}
/* 定时器0 中断程序 */
ISR(TIMER0_OVF_vect )
{
Timer0_stop;
rec_complete = 1;
}
void Timer0_init(void)
{
TIMSK |=_BV(TOIE0); //timer interrupt sources
Timer0_star;
}
void modbus_Communication(void)
{
unsigned short crcresult;
unsigned char temp[2];
unsigned char i;
crcresult= getcrc16(rec_data,rec_counter-2);
temp[1]=crcresult & 0xff;
temp[0]=(crcresult>> 8) & 0xff;
if((rec_data[0]==ADDR)&&(rec_data[rec_counter-1]==temp[0])
&&(rec_data[rec_counter-2]==temp[1]))
{
send_data[0]=ADDR;
send_data[1]=rec_data[1];
switch(rec_data[1])
{
case 0x01:
Modbus_Function_1();
break;
case 0x03:
Modbus_Function_3();
break;
case 0x05:
Modbus_Function_5();
break;
case 0x02:
Modbus_Function_2();
break;
case 0x10:
Modbus_Function_16();
break;
default:
{
send_data[1]=rec_data[1]+0x80;
send_data[2]=1;
send_counter=3;
}
}
crcresult= getcrc16(send_data,send_counter);
send_data[send_counter++]=crcresult & 0xff;
send_data[send_counter++]=(crcresult>> 8) & 0xff;
for(i=0;i<send_counter;i++)USART_Transmit(send_data);
}
}
int main(void)
{
cli();
Timer0_init();
USART_Init(BAUD);//设定串口
MCUCR = 0x00;
GIMSK = 0x00;
// wdt_enable(WDTO_15MS);
sei();
while(1)
{
sleep_enable();
sleep_cpu();
sleep_disable();
// wdt_reset();
cli();
if(rec_complete == 1)
{
rec_complete=0;
modbus_Communication();
rec_counter=0;
}
{}//数据采集
sei();
}
return (0);
} |
|