#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();
}
}