⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 b(interrupt).c

📁 PIC16C63单片机UART通信——A机读取时钟芯片DS1302获得当前时间
💻 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 + -