方法大概是这样。
main
{
if(recv_ready_flag)
{
recv_ready_flag=0;
//代码
……
//代码
RCIE=1;
}
}
中断里
ISR()
{
if(RCIE&&RCIF)
{
//代码
……
//代码
recv_ready_flag=1;
RCIE=0; //在这里关了之后,程序运行一段时间后,这里会打不开。打不开也是我的猜测,因为我把RCIE注释掉之后,程序就运行正常了。
}
}
下面是一部分实际源码,太多了,就不全弄上来了。需要说明的是,在DS18B20的函数里,转换温度和读取温度里有有先关GIE再开GIE的代码。或者是这里的问题,但我想不出来是为什么。希望各位大虾帮住看看。我做的这个东西,总的来说就是上位机每秒读取单片机转换来的温度。还可以控制一个灯的亮灭。
void main(void)
{
com_init();
time0_init();
port_init();
while(1)
{
//every time
if(recv_ready_flag)
{
recv_ready_flag=0;
switch(recv_data[2])
{
case LIGHT: //开关灯
RC4=!RC4;
if(RC4) send_value(LIGHT,'o','0');//返回灯的状态,此处为开
else send_value(LIGHT,'c','0');////返回灯的状态,此处为关
break;
case TEMP://读取温度
convert_data();
send_value('t',temp_dataed[0],temp_dataed[1]);
break;
case '1':
break;
case '2':
break;
default:
break;
}
RCIE=1;
}
//every_10ms
if(flag_10ms)
{
flag_10ms=0;
}
//every_1000ms
if(flag_1000ms)
{
flag_temp=!flag_temp;
flag_1000ms=0;
if(flag_temp)
{
convert_temp();//这里面有GIE=0;GIE=1;
RA2=1;
}
else
{
RA2=0;
get_temp(temp_undata,temp_undata+1);//这里面有GIE=0;GIE=1;
}
}
}
}
void interrupt isr()
{
if(RCIE&&RCIF)
{
recv_data[recv_cnt]=RCREG;
RA2=!RA2;
//SEND();
//TXREG=0x30+recv_cnt;
//while(!TRMT);
//RECV();
if(recv_cnt==0)
{
if(recv_data[0]==':') recv_cnt++;
}
else if(recv_cnt==1)
{
if(recv_data[1]=='1') recv_cnt++;
else recv_cnt=0;
}
else if(recv_cnt==5)
{
//RA2=!RA2;
recv_cnt=0;
if(recv_data[5]==(recv_data[2]|recv_data[3]|recv_data[4]))
{
recv_ready_flag=1;
//RCIE=0;
}
}
else if(recv_cnt>5)
{
recv_cnt=0;
}
else
{
recv_cnt++;
}
}
if(T0IE&&T0IF)
{
TMR0=216;
T0IF=0;
flag_10ms=1;
if(cnt_10ms++>100)
{
cnt_10ms=0;
flag_1000ms=1;
}
}
} |