📄 b(interrupt).c
字号:
/***************************************************
本机接收A机发来时间数据,UART采用查询中断方式收发数据,
通过LCD1602显示当前时间
****************************************************/
#include<pic166x.h>
#define uchar unsigned char
#define _nop_() asm("nop")
//定义LCM接口
#define EN RA2//RA2
#define RW RA1//RA1
#define RS RA0//RA0
#define LCD PORTB //数据口
uchar line[]={"hello world!"};
uchar num[]={"0123456789:'. "};
uchar ACC,time[7],i=0;
void interrupt uart_rxd(void)
{
uchar temp;
temp=RCREG;
TXREG=temp; //时间数据以“标识码+时间”格式发送,使用0xa0~0xa6作标识码
if(temp>0x99) i=temp-0xa0;
else time[i]=temp;
//中断标志由硬件清零
}
//***********1602"忙"检测*************/
void checkbf()
{
uchar check;
TRISB=0XFF;
for(; ;)
{
RS=0; //FOR IR
RW=1; // READ
EN=1;
check=LCD;//读出液晶数据引脚(D0-D7)值,D7=0表示液晶“不忙”
EN=0;
if(!(check&0x80)) break;//不断检测,直到液晶不“忙”
}
TRISB=0X00;
}
//*************写命令字节,flag决定是否在写之前检测"忙"状态********/
void wir(uchar cc,uchar flag)
{
GIE=0; //关中断
if(flag) checkbf(); //如果flag=1,则发命令前先进行“忙”检测
RS=0; //把命令字节(cc)写入到1602的IR(指令寄存器)
RW=0; // WRITE
EN=1;
LCD=cc;//写入命令字节cc
EN=0;
GIE=1; //开关断
}
//********* 往1602发数据字节,发之前先进行“忙”检测 *************/
void wdat(uchar dat)
{
GIE=0; //关中断
checkbf();
RS=1; //把这个字节(dat)写入1602的DR(数据寄存器)
RW=0; // WRITE
EN=1;
LCD=dat; //往1602写入用来显示的数据(1个字节)
EN=0;
GIE=1; //开关断
}
//****************在1602显示屏(X,Y)坐标处显示数据dd(占屏幕一个字的位置)***********/
/*void wbyte(uchar X,uchar Y,uchar dd)
{
if(Y==1) X|=0xc0;// second line
else X|=0x80;// first line 对坐标进行处理
wir(X,1);//先写坐标
wdat(dd);//再送要显示的数据
}*/
//****************从1602显示屏(X,Y)坐标处开始显示一连串数据***********/
void wstr(uchar X,uchar Y,uchar *da)//da为待显示的字符串数组名
{
if(Y==1) X|=0xc0;//second line
else X|=0x80; //first line
wir(X,1); //先写坐标
while(*da>0) wdat(*da++); //不断往1602送字符串数据,直到字符串尾(字符串以“/0”结尾)
}
//*********5毫秒延时程序**********************/
void delay5ms()
{
uchar i,j=250;
for(i=10;i>0;i--)
while(--j);
}
//***********初始化1602**********************/
void init()
{
delay5ms();
delay5ms();
delay5ms();//初始化一般发生在上电复位后不久,延时15ms,待系统稳定下来
wir(0x38,0);
delay5ms();
wir(0x38,0);
delay5ms();
wir(0x38,0);//重复三次写入命令字节0X38,不检测忙信号
//下面命令字节的含义参照课本1602命令字表(RS=0,RW=0的)
wir(0x38,1);//功能设定:8位数据,双列字,5*7字型
wir(0x08,1);//turn off light
wir(0x01,1);// clean the screen
wir(0x0c,1);// 开显示屏,不开游标和闪烁功能
wir(0x06,1);//设定AC+1
}
/**************UART communication****************/
void init_uart()
{
TRISC=0x80;
SPBRG=25;
SPEN=1; //open serial port
CREN=1;
TXEN=1;
GIE=1;
PEIE=1;
RCIE=1; // 开中断
}
/*
void send_byte(uchar dat)
{
TXREG=dat;
do{
; }while(!TXIF);
}
uchar rec_byte()
{
if(RCIF) return RCREG;
else return 0xff;
}
gettime(uchar *dat)
{
uchar i,temp;
for(i=7;i>0;i--)
{
for(;;)
{
temp=rec_byte();
if(temp!=0xff) break;
}
*dat++=temp;
send_byte(temp);
}
}
*/
/*************主函数main**************************/
void main()
{
uchar temp;
TRISA=0x00; //output
TRISB=0X00; //output(LCD DATA)
init_uart();
init();//初始化1602
while(1)
{
// gettime(time); //接收A机发来时间数据
wstr(0,0,line);//以字符串写入方式显示字符串line内容
wir(0xc0,1); //写入第二行首坐标0xc0
temp=time[4];
temp>>=4;
temp&=0x0f;
wdat(num[temp]);
temp=time[4];
temp&=0x0f;
wdat(num[temp]);
wdat('.'); //"."
temp=time[3];
temp>>=4;
temp&=0x0f;
wdat(num[temp]);
temp=time[3];
temp&=0x0f;
wdat(num[temp]);
wdat(' ');
temp=time[2];
temp>>=4;
temp&=0x0f;
wdat(num[temp]);
temp=time[2];
temp&=0x0f;
wdat(num[temp]);
wdat(':');
temp=time[1];
temp>>=4;
temp&=0x0f;
wdat(num[temp]);
temp=time[1];
temp&=0x0f;
wdat(num[temp]);
wdat(num[11]); // '
temp=time[0];
temp>>=4;
temp&=0x0f;
wdat(num[temp]);
temp=time[0];
temp&=0x0f;
wdat(num[temp]);
}
}
/*
wbyte(0,1,num[1]);
// wir(0xc0,1); //写入第二行首坐标0xc0
// wdat(num[1]); //之后不断往1602送数据,每送一个字节,1602地址会自动加1
wdat(num[2]); //这样后面的数据才不会覆盖前面的
wdat(num[12]);
wdat(num[1]);
wdat(num[8]);
wdat(num[13]);
// wir(0xc7,1); //改变1602内部地址寄存器值,即自己挑选显示位置
wdat(num[1]);
// wir(0xca,1);
wdat(num[3]);
wdat(num[10]);
wdat(num[1]);
wdat(num[9]);
wdat(num[11]);
*/
//控制1602显示可以采用“写坐标+写数据”,“写坐标+写数据”在屏上特定位置显示一个字,
//也可以写入一个坐标后不断写入数据,直到该屏幕的最末(如上例)。
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -