PIC16F877驱动KS0066U液晶程序

2019-04-15 16:44发布

为了电子设计大赛,我又要重新学习单片机了! 现在来总结总结以前学习单片机的经验和体会: 1、单片机其实并不难,无非就是那几个模块,而真正难的是:一个外围芯片(比如下面将要驱动的液晶芯片)的工作时序以及准确的延时;然后利用单片机的资源去按照时序编程就得了,所以说了只要把一种单片机的常用模块搞通了,其它也就一样简单,很容易就OK了! 2、单片机编程的框架:模块的初始化,然后死循环和中断,很简单吧! 3、单片机编程应该注意的问题,一是要按照说明书给出的时序来编程,不要自己想当然了;二是要控制好延时,大部分单片机系统的不稳定,有很多是因为延时不到位引起的;而对PIC等单片机来说,还得注意使用时一定得注意单片机的端口的方向(输入还是输出)! 本驱动采用4bit,2-line模式电路图如下: KS0066U液晶电路连线图   液晶驱动程序头文件 #ifndef LCD_H
#define LCD_H
#include ”main.h“
#define uchar unsigned char
//define port function
#define LCD_DB7     RB5  //;//占用的I/O口定义  
#define LCD_DB6     RB4  //;//该行硬件连接:LCD的DB6与RB4连接,其它类推
#define LCD_DB5     RB3  //;
#define LCD_DB4     RB2  //;
#define LCD_E     RA3  //;
#define LCD_RS     RB1  //;
#define LCD_DB7_DIR TRISB5   //;//对应的方向寄存器定义
#define LCD_DB6_DIR TRISB4   //;
#define LCD_DB5_DIR TRISB3   //;
#define LCD_DB4_DIR TRISB2   //;
#define LCD_E_DIR TRISA3   //;
#define LCD_RS_DIR TRISB1   //;
//define commad
#define LCD_FUNC_MODE 0x28 //4bit 2-line 5*8dots
#define LCD_CURSE_MODE0 0x0c //display :on ,curse :off,blink :offf
#define LCD_CURSE_MODE1 0x0e //lcd display  curse display
#define LCD_CURSE_MODE2 0x0f //lcd display curse display curse blink
#define LCD_CLR_DISP 0x01 //clear display
#define LCD_BEGIN_ADD 0x80 //set begin address
#define LCD_SHIFT_RIGHT_ALL 0x05 //shift entire display in rightt direction
#define LCD_SHIFT_LEFT_ALL 0x07 //shirft left entire
#define LCD_CURSE_RIGHT 0x14//curse shift right
#define LCD_CURSE_LEFT 0x10 //curse shift left ;
#define LCD_DISP_LEFT 0x18//shift display in left direction
#define LCD_DISP_RIGHT 0x1C//shift display in right direction
#define LCD_SECOND_LINE 0xc0 //change line void init_lcd() ;
void write_in() ;
void sendcmd(char cddata);
void putclcd(char data) ;
void printlcd(const char *data) ;
void write(char data) ;
void delay(unsigned int count) ;
void lcd_shift(uchar flag,uchar count) ;
void curse_shift(uchar flag,uchar count) ;
void delay_long() ;
#endif
液晶驱动程序 #include "lcd.h"
void init_lcd()
{
//设置端口输出模式
  LCD_DB7_DIR=0;
  LCD_DB6_DIR=0;
  LCD_DB5_DIR=0;
  LCD_DB4_DIR=0;
  LCD_E_DIR=0;
  LCD_RS_DIR=0; //清除数据线
  LCD_DB7=0;
  asm("nop");
  LCD_DB6=0;
  asm("nop");
  LCD_DB5=0;
  asm("nop");
  LCD_DB4=0;
  asm("nop");
  LCD_RS=0;
  asm("nop");
 
  LCD_E=0;
  asm("nop");
//将上述命令设置生效
  write_in() ;
 delay(0xffff) ;
 delay(0xffff) ;
//设置功能模式,4bit,2-line.5*8dots
 sendcmd(0x28) ;
 sendcmd(0x0c) ;//启动显示,光标不显示,光标不闪烁
 sendcmd(0x80) ;//设置起始地址
 sendcmd(0x01) ;//清屏
 
}
/*********************8
10us级延时
***********************/
void delay(unsigned int count)

 while(count)
    count-=1;
}
/*************************************
使写入生效
****************************************/
void write_in()
{
 asm("nop") ;
 LCD_E=1 ;
 asm("nop") ;
 LCD_E=0 ;
 asm("nop") ;
}
/***********************************
发送指令
*************************************/
void sendcmd(char cmdata)
{
   LCD_RS=0;                //设置为送命令模式,与PUTCLCD仅相差此行
    write(cmdata);           //写入全字节
 //delay(255);
}
/********************************************
显示单个字符
********************************************/
void putclcd(char lcdbyte)
{
    LCD_RS=1;//设置为发送数据模式
 write(lcdbyte);
 //   delay(255);
}
/**************************************
*显示字符串
*************************************/
void printlcd(const char *lcdata)
{
    while((*lcdata)!='/0')
    {
       putclcd(*lcdata++);      
    }
}
/**********************************************
*写入单个字节
**********************************************/
void write(char wdata)
{
   char temp=wdata;
   LCD_DB7=0;
   LCD_DB6=0;
   LCD_DB5=0;
   LCD_DB4=0;
   if(temp&0X80)
   LCD_DB7=1;
   if(temp&0X40)
   LCD_DB6=1;
   if(temp&0X20)
   LCD_DB5=1;
   if(temp&0X10)
   LCD_DB4=1;
   write_in() ;    temp=wdata<<4; 
   LCD_DB7=0;
   LCD_DB6=0;
   LCD_DB5=0;
   LCD_DB4=0;
   if(temp&0X80)
   LCD_DB7=1;
   if(temp&0X40)
   LCD_DB6=1;
   if(temp&0X20)
   LCD_DB5=1;
   if(temp&0X10)
   LCD_DB4=1;
   write_in() ;
   delay(160);   
} /*************************************
*功能:移动显示:如果把延时改动一下可以改变显示移动的速冻
*输入参数:flag=0  shift left ;flag=1 shift right ;count :the bit og shift 
******************************/
void lcd_shift(uchar flag,uchar count)
{
 uchar i ;
 if(flag==0)
 {
  for(i=0;i  {
  // delay(0xfff) ;
   delay_long() ;
   sendcmd(LCD_DISP_LEFT) ;
  }
 } 
 else
 {
  for(i=0;i  {
   delay_long() ;
   sendcmd(LCD_DISP_RIGHT) ;
  } 
 }
}
/*****************************
*功能:光标移动
*输入参数:flag=0  shift left ;flag=1 shift right ;count :the bit og shift 
**************************/
void curse_shift(uchar flag,uchar count)
{
 uchar i ;
 if(flag==0)
 {
  for(i=0;i  {
  // delay_long() ;
   sendcmd(LCD_CURSE_LEFT) ;
  }
 } 
 else
 {
  for(i=0;i  {
  // delay_long() ;
   sendcmd(LCD_CURSE_RIGHT) ;
  } 
 }
}
void delay_long()
{
 unsigned char i ;
 for(i=0;i<2;i++)
  delay(0x4ff1) ;
}