首页 > 代码库 > modbus.c

modbus.c

#include <avr/io.h>#include <avr/interrupt.h>#include <util/delay.h>//#include <avr/wdt.h>#define SYNC 0x40#define PARITY_EVEN 0x20#define PARITY_ODD 0x30#define STOP_2 0x04#define DATA_5 0x00#define DATA_6 0x02#define DATA_7 0x04#define DATA_8 0x06 //最高位置1,UMSELn设为0工作于异步模式#define DATA_9 0x0c#define FRAMING_ERROR (1<<FE)#define PARITY_ERROR (1<<UPE)#define DATA_OVERRUN (1<<DOR)#define DATA_REGISTER_EMPTY (1<<UDRE)#define RX_COMPLETE (1<<RXC)#define SYSTEM_CLOCK 16000000L#define BAUD_RATE 38400L//57600L测试通过#define UART_RX_BUFFER_SIZE 1024#define UART_RX_BUFFER_MASK (UART_RX_BUFFER_SIZE-1)#if (UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK)#error RX buffer size is not a power of 2#endif#define UART_TX_BUFFER_SIZE 512#define UART_TX_BUFFER_MASK (UART_TX_BUFFER_SIZE-1)//UART_RX_BUFFER_SIZE 128#if (UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK)#error TX buffer size is not a power of 2#endifvolatile static unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];//UART_RX_BUFFER_SIZE 128volatile static unsigned char UART_RxHead;volatile static unsigned char UART_RxTail;volatile static unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];//UART_TX_BUFFER_SIZE 128volatile static unsigned char UART_TxHead;volatile static unsigned char UART_TxTail;//volatile static unsigned char UART0_RxBuf[UART_RX_BUFFER_SIZE];//UART_RX_BUFFER_SIZE 128volatile static unsigned char UART0_RxHead;volatile static unsigned char UART0_RxTail;volatile static unsigned int UART0_TxBuf[UART_TX_BUFFER_SIZE];//UART_TX_BUFFER_SIZE 128volatile static unsigned char UART0_TxHead;volatile static unsigned char UART0_TxTail;//volatile static unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];//UART_RX_BUFFER_SIZE 128volatile static unsigned char UART1_RxHead;volatile static unsigned char UART1_RxTail;volatile static unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];//UART_TX_BUFFER_SIZE 128volatile static unsigned char UART1_TxHead;volatile static unsigned char UART1_TxTail;void Initialize(void);void Serial_Initialize_UART0(unsigned long int baud);void Serial_Initialize_UART1(unsigned long int baud);void Timer0_Initialize(void);void Timer3_Initialize(void);unsigned char UART0_ReceiveByte(void);void UART0_TransmitByte(unsigned char data);unsigned char UART1_ReceiveByte(void);void UART1_TransmitByte(unsigned char data);void UART0_TransmitC(unsigned char c);void UART0_TransmitString(unsigned char *ptr);void UART1_TransmitC(unsigned char c);void UART1_TransmitString(unsigned char *ptr);void SendDataUp();void SendDataDown(void);extern unsigned char ReadTime(void);unsigned char strCat(unsigned char *s1,unsigned char *s2);void Initialize(void){     //MCUCR=0x00;//PORTA,PORTC作普通口使用	 Serial_Initialize_UART0(BAUD_RATE);	 Serial_Initialize_UART1(BAUD_RATE);	 //Timer0_Initialize();	 Timer3_Initialize();	 sei();	}void Serial_Initialize_UART0(unsigned long int baud){	 unsigned short int ubrr0;	 ubrr0=((SYSTEM_CLOCK/(16L*baud))-1);	 UBRR0H=(unsigned char)(ubrr0>>8);//设置USART0波特率	 UBRR0L=(unsigned char)ubrr0;	 //UCSR0B=((1<<TXCIE0)|(1<<RXCIE0)|(1<<RXEN0)|(1<<TXEN0));//USART0接收结束中断使能,接收器发送器使能	 UCSR0B=((1<<RXEN0)|(1<<TXEN0));	//初始化时先先进入定时中断,屏蔽接收发送中断,	 UCSR0C=DATA_8; //异步,无奇偶校验,1位停止位,8数据位	 	 UART0_RxTail=0;	 UART0_RxHead=0;	 UART0_TxTail=0;	 UART0_TxHead=0;}void Serial_Initialize_UART1(unsigned long int baud){	 unsigned short int ubrr1;	 ubrr1=((SYSTEM_CLOCK/(16L*baud))-1);	 UBRR1H=(unsigned char)(ubrr1>>8);//设置USART1波特率	 UBRR1L=(unsigned char)ubrr1;	 //UCSR1B=((1<<TXCIE1)|(1<<RXCIE1)|(1<<RXEN1)|(1<<TXEN1));//USART1接收结束中断使能,接收器发送器使能	 UCSR1B=((1<<RXEN1)|(1<<TXEN1));//初始化时先不打开接收发送中断	 UCSR1C=DATA_8; //异步,无奇偶校验,1位停止位,8数据位	 	 UART1_RxTail=0;	 UART1_RxHead=0;	 UART1_TxTail=0;	 UART1_TxHead=0;}void Timer0_Initialize(void){	cli();	TCNT0=0x63;//((0xff-0x63)+1)*1024*(1/16M)=10ms	TCCR0=0x07;//定时器0 预分频比1024	TIMSK=0x01;//开定时器0中断}void Timer3_Initialize(void){	TCCR3B = 0x00;  //stop timer 	//0.1s  0xffff+1-(16M/1024)*0.1=63973.5--0xf9e5	//0.2s--0xf3cb	//0.3s--0xEDB0	//TCNT3H=0xff;	//TCNT3L=0x64;	//TCCR3B=0x05;//1024预分频	TCNT3H=0xf3;	TCNT3L=0xcb;	TCCR3B=0x04;//256预分频	ETIMSK|= (1 << TOIE3);//定时器3溢出中断}//由于单片机要实现和DTU与modbus模块的同时通讯,采用双串口CPU,//串口0中断处理与DTU的数据通讯,串口1中断处理与modbus数据采集模块的通讯,//串口0中断设置为高优先级中断,每接收到或发送完一个字节都进入中断处理,处理完毕立即退出中断//通讯波特率都为38400 b/s,一个起始位,一个停止位。//时间冲突问题,硬件接受或发送一个字节的时间为1 ms左右,而软件接受或发送一个字节的时间仅几μs。//同时通讯实际上是将CPU时间分成很小的时间片,假设较快的串口发送或接受一个字节的最长时间为TRbyteMax,则CPU最长时间片一般应小于TRbyteMax/2,当然在接受或发送完一帧数据之后的间隙,CPU时间片可以适当延长,作一些必要的数据处理。 //数据冲突问题,2个串口通讯分别使用各自的接受发送数据缓冲区和控制变量, //以减少中断保护数据量和防止数据冲突。 //当主程序、串口2中断处理程序和其他中断处理程序往存储器中写数据时, //需在尽量短的时间内关闭串口1中断,关闭中断时间应小于几百μs, //防止其他程序数据没有写完之前串口1读此数据。//UART0接收完成中断SIGNAL(SIG_UART0_RECV){     unsigned char data;	 unsigned char tmphead;	 	 data=http://www.mamicode.com/UDR0;//read the received data"wdr");			//clr wdt	WDTCR=0x0F;			//enable wdt,clk = 2048,1.8S}void watchdog_on(void) {	//看门狗计数清零 	asm("WDR");			 	//WDTCR=0x1F;  	//使能watchdog,并且,采用1024K分频,典型溢出时间5V时1S  	WDTCR = (1 << WDE)|(1 << WDP2) | (1 << WDP1) | (1 << WDP0); // 启动看门狗定时, 复位周期为1S} void WDT_off(void){	//WDT复位	asm("wdr");	//置位WDCE 和 WDE	WDTCR = (1<<WDCE) | (1<<WDE);	//关闭WDT	WDTCR = 0x00;}*/unsigned short crc16(unsigned char* puchMsg, unsigned char usDataLen);//往服务器发送数据void ReadHoldRegister(void){		/*		unsigned char data_up;	unsigned char CompayID[]={"shanghailianxun "};	unsigned char DeviceCode[]={"DeviceCode "};	unsigned char TransmitTimeStamp[]={"TimeStamp "};	unsigned char DDC_Name[]={"DDC_0001 "};	unsigned char NV_Name[]={"NV_001 "};	unsigned char State[]={"State "};	unsigned char Space[]={" "};	unsigned char NVF[]={"NVF "};	unsigned char CRCCode16[]={"CRCCode"};	//TransmitTimeStamp[] = ReadTime();				UCSR0B |=(1<<RXCIE0);//开USART0收中断					UCSR1B |=(1<<TXCIE1);//开USART1发中断								UART1_Transmit_String(CompayID);								UART1_Transmit_String(DeviceCode);								UART1_Transmit_String(TransmitTimeStamp);								UART1_Transmit_String(DDC_Name);								UART1_Transmit_String(NV_Name);								UART1_Transmit_String(State);								UART1_TransmitByte(data_up);								//UART1_Transmit_String(UART0_RxBuf);								UART1_Transmit_String(Space);								UART1_Transmit_String(NVF);								UART1_Transmit_String(CRCCode16);								UART1_TransmitByte(‘\r‘);								UART1_TransmitByte(‘\n‘);				UCSR0B &=~(1<<RXCIE0); UCSR1B &=~(1<<TXCIE1);//关		*/     	unsigned char TransmitBuff[8] = {0};	 	TransmitBuff[0] = 0x01;     	TransmitBuff[1] = 0x03; 		TransmitBuff[2] = 0x00; 	 	TransmitBuff[3] = 0x00; 	 	TransmitBuff[4] = 0x00;     	TransmitBuff[5] = 0x0f;		unsigned short wCrc = 0;		wCrc = crc16(TransmitBuff, 6); 	 	TransmitBuff[6] = (wCrc &0xFF00)>>8; 	 	TransmitBuff[7] = (unsigned char)(wCrc &0x00FF);				cli();//发送前清除所有中断	 	UART0_Transmit_HEX(TransmitBuff,8);		sei();//发送完成后打开中断		//UCSR0B |= (1<<RXCIE0);		UART0_ReceiveData();		_delay_ms(30);/*		_delay_ms(20);		_delay_ms(20);		_delay_ms(20);		_delay_ms(20);		_delay_ms(20);		_delay_ms(20);		_delay_ms(20);		_delay_ms(20);*/		cli();  		UART1_Transmit_HEX(UART0_RxBuf,36);    		sei();  	 	//_delay_ms(100);	 //data_up=UART0_ReceiveByte();/*       unsigned char ReceiveBuff[128] = {0};	 for (int n=0; n<35; n++)	 	{	 	    ReceiveBuff[n]=UART0_Receive();	 	}	 	 UART1_Transmit_HEX(ReceiveBuff,35 );*/	 }//往设备发送数据void SendDataDown(void){					//unsigned char data_down;	//unsigned char CompayID[]={"shanghailianxun "};	unsigned char DeviceCode[]={"DeviceCode "};	unsigned char TransmitTimeStamp[]={"TimeStamp "};	unsigned char DDC_Name[]={"DDC_0001 "};	unsigned char NV_Name[]={"NV_001 "};	unsigned char State[]={"State "};	unsigned char Space[]={" "};	unsigned char NVF[]={"NVF "};	unsigned char CRCCode16[]={"CRCCode"};					//data_down=UART1_ReceiveByte();					//ReadTime();					{							UART0_Transmit_String(DeviceCode);							UART0_Transmit_String(TransmitTimeStamp);							UART0_Transmit_String(DDC_Name);							UART0_Transmit_String(NV_Name);							UART0_Transmit_String(State);							//UART0_TransmitByte(data_down);							UART0_Transmit_String(UART1_RxBuf);							UART0_Transmit_String(Space);							UART0_Transmit_String(NVF);							UART0_Transmit_String(CRCCode16);							UART0_TransmitByte(‘\r‘);							UART0_TransmitByte(‘\n‘);					}}int main(void){	//unsigned char code str[] = "shanghailianxun";	//unsigned char *pstr = str;	//while(*pstr)	//{  		//send_a_char(*pstr);  		//pstr ++;	//}     Initialize();	 //PORTB=0xff;	 //watchdog_on();    //_delay_ms(100);	//UART1_Transmit_String(string1);	//UART1_TransmitByte(‘\n‘);	while(1)		{			//data_down=UART1_ReceiveByte();			;			//ReadHoldRegister();			//SendDataDown();		}}

  

modbus.c