ATMEGA16单片机与MCGS通信MODBUSRTU协议Word格式文档下载.docx
《ATMEGA16单片机与MCGS通信MODBUSRTU协议Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《ATMEGA16单片机与MCGS通信MODBUSRTU协议Word格式文档下载.docx(18页珍藏版)》请在冰点文库上搜索。
(UCSRA&
(1<
UDRE)));
/*将数据放入缓冲器,发送数据*/
UDR=data;
}
//发送字符串
voidsend_string(uchar*p,ucharmend)
{
uchark=0;
for(k=0;
k<
mend;
k++)
send_char(*p++);
voidinti_port()
{
DDRB=0xff;
PORTB=0xff;
DDRC=0xff;
PORTC=0x00;
//CRC效验,将结果存储到CRCok变量中。
checkcrc(uchar*q,ucharnend)
uintwcrc=0xffff;
intj=0,i=0;
for(i=0;
i<
nend;
i++)
wcrc^=*q++;
for(j=0;
j<
8;
j++)
if(wcrc&
1)
{
wcrc>
>
=1;
wcrc^=0xa001;
}
else
wcrc>
}
crcl=wcrc;
crch=wcrc>
intmain(void)
inti_uart();
inti_port();
INT_Init();
sei();
while
(1)
gettemp();
_delay_ms(1050);
SIGNAL(SIG_UART_RECV)
rx[renum++]=UDR;
if(renum==8)
renum=0;
switch(rx[1])
case0x01:
if(!
rx[3])
tx[0]=rx[0];
//leD灯
tx[1]=rx[1];
tx[2]=0x01;
DDRB=0X00;
tx[3]=PORTB;
DDRB=0XFF;
checkcrc(tx,4);
tx[4]=crcl;
tx[5]=crch;
send_string(tx,6);
break;
}
else
{
//继电器和蜂鸣器
DDRC=0X00;
tx[3]=PORTC;
tx[3]>
=7;
DDRC=0XFF;
case0x04:
tx[0]=rx[0];
tx[2]=rx[5]<
1;
tx[3]=0x00;
tx[4]=teml;
tx[5]=0x00;
tx[6]=temh;
checkcrc(tx,nend=tx[2]+3);
tx[tx[2]+3]=crcl;
tx[tx[2]+4]=crch;
send_string(tx,mend=tx[2]+5);
case0x05:
DDRB=0XFF;
switch(rx[3])
case0x00:
if(!
rx[4])
PORTB&
=~(1<
PB0);
else
PORTB|=(1<
break;
case0x01:
PB1);
case0x02:
PB2);
case0x03:
PB3);
case0x04:
PB4);
case0x05:
PB5);
case0x06:
PB6);
case0x07:
PB7);
case0x08:
if(rx[4])
PORTC|=(1<
PC7);
PORTC&
}
send_string(rx,8);
default:
break;
}
//*****************************红外线接收**********************************************//
//外部中断初始化
voidINT_Init(void)
MCUCR|=_BV(ISC01);
//选择外部中断0,下降沿触发中断
MCUCR&
=~_BV(ISC00);
//10:
INT0的下降沿产生异步中断请求
GICR|=(1<
INT0);
//使能外部中断请求0
DDRD&
=~_BV(PD2);
//设置为输入,
PORTD|=_BV(PD2);
//使能上拉电阻
SIGNAL(SIG_INTERRUPT0)
cli();
uchari,j,k=0,addr[4]={0};
GICR&
=~(1<
//禁止外部中断INT0关闭外部中断,开始接受数据
for(i=0;
i<
14;
_delay_us(400);
if(PIND&
(1<
PD2))//9MS内有高电平,则判断为干扰,退出处理程序
//使能外部中断INT0
return;
while(!
(PIND&
PD2)));
//等待9ms低电平过去
4;
i++)//
for(j=0;
j<
8;
j++)//
while(PIND&
PD2));
//等待4.5ms高电平过去
//等待变高电平
PD2))//计算高电平时间
_delay_us(100);
k++;
if(k>
=30)//高电平时间过长,则退出处理程序
//
addr[i]=addr[i]>
1;
//接受一位数据
=8)
addr[i]=addr[i]|0x80;
//高电平时间大于0.56,则为数据1
k=0;
//计时清零
switch(addr[3])
DDRB=0XFF;
case0x07:
if(a1)
{
PORTB&
a1=0;
}
else
{
PORTB|=(1<
a1=1;
break;
//1
case0x0b:
if(a2)
a2=0;
a2=1;
break;
//2
case0x0f:
if(a3)
a3=0;
a3=1;
//3
case0x13:
if(a4)
a4=0;
a4=1;
//4
case0x17:
if(a5)
a5=0;
a5=1;
//5
case0x1b:
if(a6)
a6=0;
a6=1;
//6
case0x1f:
if(a7)
a7=0;
a7=1;
//7
case0x23:
if(a8)
a8=0;
a8=1;
//8
case0x03:
if(a9)//蜂鸣器和继电器
PORTC|=(1<
a9=0;
PORTC&
a9=1;
case0x27:
PORTB=0X00;
break;
//9
case0x2b:
PORTB=0XFF;
//空格*/
#ifndef__ds18b20__H
#define__ds18b20__H
#defineuintunsignedint
#defineCLR_DIR_1WIREDDRC&
PC6)//不再变化
#defineSET_DIR_1WIREDDRC|=(1<
PC6)//IO改为输入口,高阻态,外部上拉电阻拉高
#defineSET_OP_1WIREPORTC|=(1<
PC6)//改为输出口,输出低电平
#defineCLR_OP_1WIREPORTC&
=~(1<
PC6)
#defineCHECK_IP_1WIRE(PINC&
0x40)
voidinit_1820(void);
voidwrite_1820(unsignedcharx);
unsignedcharread_1820(void);
voidgettemp(void);
volatileuintTemperature;
volatileunsignedchartemh,teml;
volatileucharNum[4];
voidinit_1820(void)
SET_DIR_1WIRE;
//设置PA0为输出
SET_OP_1WIRE;
//输出1
CLR_OP_1WIRE;
//输出0
_delay_us(480);
//480us以上
CLR_DIR_1WIRE;
//设置PA0为输入
_delay_us(20);
//15~60us
while(CHECK_IP_1WIRE);
_delay_us(140);
//60~240us
}
voidwrite_1820(unsignedcharx)
unsignedcharm;
for(m=0;
m<
m++)
if(x&
(1<
m))//写数据了,先写低位的!
else
{CLR_OP_1WIRE;
_delay_us(40);
unsignedcharread_1820(void)
unsignedchartemp,k,n;
temp=0;
for(n=0;
n<
n++)
k=(CHECK_IP_1WIRE);
//读数据,从低位开始
if(k)
temp|=(1<
n);
temp&
_delay_us(50);
//60~120us
return(temp);
voidgettemp(void)//读取温度值
init_1820();
//复位18b20
write_1820(0xcc);
//发出转换命令
write_1820(0x44);
//_delay_ms(10);
//不延时也好使,不知道怎么回事!
//发出读命令
write_1820(0xbe);
teml=read_1820();
//读数据
temh=read_1820();
#endif