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

#endif



volatile static unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];//UART_RX_BUFFER_SIZE 128

volatile 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 128

volatile 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 128

volatile 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 128

volatile 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 128

volatile 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 128

volatile 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=UDR0;//read the received data

	 //calculate buffer index

	 tmphead=(UART0_RxHead+1)&UART_RX_BUFFER_MASK;//UART_RX_BUFFER_MASK 127

	 UART0_RxHead=tmphead;//store new index

	 

     if(tmphead==UART0_RxTail)

	 	 {

		 	//ERROR! Receive buffer overflow

	     }

	 UART0_RxBuf[tmphead]=data; //store received data in buffer

	 //if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)

}





void UART0_ReceiveData(void)

{  

	 unsigned char UART0_RxBuf[UART_RX_BUFFER_SIZE] = {0};



	 UCSR0B |= (1<<RXCIE0);

}





//UART1接收完成中断

SIGNAL(SIG_UART1_RECV)

{

     unsigned char data;

	 unsigned char tmphead;

	 

	 data=UDR1;/* read the received data */

	 //calculate buffer index

	 tmphead=(UART1_RxHead+1)&UART_RX_BUFFER_MASK;//UART_RX_BUFFER_MASK 127

	 UART1_RxHead=tmphead;//store new index

	 

     if(tmphead==UART1_RxTail)

	 	 {

		 	/* ERROR! Receive buffer overflow */

	     }

	 UART1_RxBuf[tmphead]=data; //store received data in buffer

}





//UART0数据寄存器空中断

SIGNAL(SIG_UART0_DATA)

{

     unsigned char tmptail;

	 

	 if(UART0_TxHead!=UART0_TxTail)//check if all data is transmitted

	 	{

			/* calculate buffer index */

	     	tmptail=(UART0_TxTail+1)&UART_TX_BUFFER_MASK;//UART_TX_BUFFER_SIZE 128

		 	UART0_TxTail=tmptail;//store new index

		 	UDR0=UART0_TxBuf[tmptail];//start transmition

		 }

	 else

	 	{

	     	UCSR0B&=~(1<<UDRIE);//disable UDRE interrupt

		 }

}





//UART1数据寄存器空中断

SIGNAL(SIG_UART1_DATA)

//SIGNAL(SIG_UART1_TRANS)

{

     unsigned char tmptail;

	 

	 if(UART1_TxHead!=UART1_TxTail)//check if all data is transmitted

	 	{

		/* calculate buffer index */

	     tmptail=(UART1_TxTail+1)&UART_TX_BUFFER_MASK;//UART_TX_BUFFER_SIZE 128

		 UART1_TxTail=tmptail;//store new index

		 UDR1=UART1_TxBuf[tmptail];//start transmition

		 }

	 else

	 	{

	     	UCSR1B&=~(1<<UDRIE);//disable UDRE interrupt

		 }

}





unsigned char timer0count=0;

void ReadHoldRegister(void);



SIGNAL(SIG_OVERFLOW0)

{	

	TIMSK=0x00;//关定时器0中断



	timer0count++;



	//DDRA  |=(1<<3);//测试能否进入溢出中断

	//PORTA |=(1<<3);

	//_delay_ms(3000);

	//PORTA &=~(1<<3);

	//_delay_ms(3000);

	

	ReadHoldRegister();



	if(timer0count==15)	//150ms

	{

		//sendcommand(3,0x03,0x01);//读输入寄存器,startAddr,RegNum

		TIMSK=0x01;//开定时器0中断

	}

}





SIGNAL(SIG_OVERFLOW3)

{

	ETIMSK=0x00;//关定时器3溢出中断

	//DDRA  |=(1<<3);//测试能否进入溢出中断

	//PORTA ^=(1<<3);

	ReadHoldRegister();



	ETIMSK|= (1 << TOIE3);//开定时器3溢出中断

}







//将两个字符串连接起来

unsigned char strCat(unsigned char *s1,unsigned char *s2)

{

	int i=0,j=0;

	while(s1[i]!='\0')

		i++;

	while(s2[j]!='\0')

		s1[i++]=s2[j++];

	s1[i]='\0';

	return *s1;

}



	 

unsigned char UART0_ReceiveByte(void)

{

     unsigned char tmptail;

	 while(UART0_RxHead==UART0_RxTail);//wait for incoming data

	 //caculate buffer index

	 tmptail=(UART0_RxTail+1)&UART_RX_BUFFER_MASK;//UART_RX_BUFFER_MASK 127

	 UART0_RxTail=tmptail;//store new index

	 return UART0_RxBuf[tmptail];//return data

}





unsigned char UART1_ReceiveByte(void)

{

     unsigned char tmptail;

	 while(UART1_RxHead==UART1_RxTail);//wait for incoming data

	 //caculate buffer index

	 tmptail=(UART1_RxTail+1)&UART_RX_BUFFER_MASK;//UART_RX_BUFFER_MASK 127

	 UART1_RxTail=tmptail;//store new index

	 return UART1_RxBuf[tmptail];//return data

}





//发送采用查询方式

//USART0发送字符

unsigned char UART0_Receive(void) 

{

	/* 等待接收数据*/

	while ( !(UCSR0A & (1<<RXC0)) )

		;

	/* 从缓冲器中获取并返回数据*/

	return UDR0;

}







void UART0_TransmitByte(unsigned char data)

{

     unsigned char tmphead;

	 //caculate buffer index

	 tmphead=(UART0_TxHead+1)&UART_TX_BUFFER_MASK;//UART_TX_BUFFER_SIZE 128

	 while(tmphead==UART0_TxTail);//wait for free space in buffer

	 

	 UART0_TxBuf[tmphead]=data;//store new data in buffer

	 UART0_TxHead=tmphead;//store new index

	 UCSR0B|=(1<<UDRIE);//enable UDRIE interrupt

}



void UART1_TransmitByte(unsigned char data)

{

     unsigned char tmphead;

	 //caculate buffer index

	 tmphead=(UART1_TxHead+1)&UART_TX_BUFFER_MASK;//UART_TX_BUFFER_SIZE 128

	 while(tmphead==UART1_TxTail);//wait for free space in buffer

	 

	 UART1_TxBuf[tmphead]=data;//store new data in buffer

	 UART1_TxHead=tmphead;//store new index

	 UCSR1B|=(1<<UDRIE);//enable UDRIE interrupt

}





//发送采用查询方式

//USART0发送字符

void UART0_Transmit_c(unsigned char c) 

{

 	while(!(UCSR0A & (1<<UDRE)));//wait for empty transmit buffer

 	UDR0=c;

}



	 

//USART1发送字符

void UART1_Transmit_c(unsigned char c) //发送采用查询方式

{

 	while(!(UCSR1A & (1<<UDRE)));//wait for empty transmit buffer

 	UDR1=c;

}





void UART0_Transmit_String(unsigned char *ptr)

{

 	while (*ptr)

 	{

  		UART0_TransmitByte(*ptr++);

 	}

 	UART0_Transmit_c(0x0D);//结尾发送回车

 	UART0_Transmit_c(0x0A);//结尾发送换行

}





//USART1发送字符串

void UART1_Transmit_String(unsigned char *ptr)

{

 	while (*ptr)

 	{

  		UART1_TransmitByte(*ptr++);

 	}

 	UART1_Transmit_c(0x0D);//结尾发送回车

 	UART1_Transmit_c(0x0A);//结尾发送换行

}







void UART0_Transmit_HEX(unsigned char *ptr, int nLen)

{

 	for(int i=0; i<nLen; i++)

 	{

  		UART0_Transmit_c(ptr[i]);

 	}

}





void UART1_Transmit_HEX(unsigned char *ptr, int nLen)

{

 	for(int i=1; i<nLen; i++)

 	{

  		UART1_Transmit_c(ptr[i]);

 	}

}





/*

void wdt_init(void)

{

	asm("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();

		}

}

  

你可能感兴趣的:(DB)