为了电子设计大赛,我又要重新学习单片机了!
现在来总结总结以前学习单片机的经验和体会:
1、单片机其实并不难,无非就是那几个模块,而真正难的是:一个外围芯片(比如下面将要驱动的液晶芯片)的工作时序以及准确的延时;然后利用单片机的资源去按照时序编程就得了,所以说了只要把一种单片机的常用模块搞通了,其它也就一样简单,很容易就OK了!
2、单片机编程的框架:模块的初始化,然后死循环和中断,很简单吧!
3、单片机编程应该注意的问题,一是要按照说明书给出的时序来编程,不要自己想当然了;二是要控制好延时,大部分单片机系统的不稳定,有很多是因为延时不到位引起的;而对PIC等单片机来说,还得注意使用时一定得注意单片机的端口的方向(输入还是输出)!
本驱动采用4bit,2-line模式电路图如下:
液晶驱动程序头文件
#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) ;
}