打印

PIC16F877A和PIC16F914驱动1602液晶屏问题

[复制链接]
3917|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
544852010|  楼主 | 2012-4-17 15:24 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请教个PIC16F913和PIC16F877A  驱动1602液晶屏的问题  我用PIC16F913的程序  只切换ADCON1和ANSEL  ,和切换CONFIG就可以在877上面驱动1602,可是,913程序驱动1602,整个第一行全黑显示,但是显示很暗,几乎看不清,请问是什么原因?哪位兄弟,帮忙看下,谢谢!

877A的main.c程序:
#include <htc.h>
//#include <pic.h>
//#include <pic1687x.h>
//#include <pic16f91x.h>
#define uchar unsigned char
#define uint  unsigned int
#define TESTBIT(a,b) ((a)&(1<<(b)))
__CONFIG(WDTDIS & LVPDIS & HS & PWRTDIS & BORDIS);//设置877配置位
//__CONFIG(WDTDIS &  HS & PWRTDIS & BORDIS);//设置配置位

#define  LCD_RS  RA0
#define  LCD_RW  RA1
#define  LCD_EN      RA2

/************************定义显示字符*****************************************/
uchar tab[] = {" Welcome A Use  PIC Study Board "};
/************************声明函数*********************************************/
void DelayUS(uint);
void Delay_ms(uint delay);
uchar Chk_1602_busy(void);
void Write_1602_command(uchar gcmd,uchar gvalue);
void Write_1602_data(uchar gdata);
void INIT_1602(void);
void Display_1602_string(uchar gadd_start,uchar gline,uchar glength,uchar *pdata);
void Display_1602(uchar x,uchar y,uchar gdata);

/*******************************************************************************
* 函 数 名: DelayUS(uint8 delay)
* 函数功能: 微秒延时
* 入口参数: delay
* 返    回: 无
*******************************************************************************/
void DelayUS(uint delay)   
{
   for(;delay;)
   {
      NOP();
      delay--;
   }
}
/*******************************************************************************
* 函 数 名: DelayMS(uint16 delay)
* 函数功能: 毫秒延时
* 入口参数: delay
* 返    回: 无
*******************************************************************************/
void Delay_ms(uint delay)  
{
   uint i;
   for(i=0;i<delay;i++)
       DelayUS(1000);
}
/*******************************************************************************
* 函 数 名: Read_LCD_Busy(void)
* 函数功能: 读液晶忙通道数据
* 入口参数: 无
* 返    回: 无
*******************************************************************************/
uchar Chk_1602_busy(void)
{
   uint gR_data;
   uint gwait_time=0xff;   //设置忙超时数
   LCD_RS=0;         //表示状态
   LCD_RW=1;         //选择读
   LCD_EN=1;
   TRISC = 0xFF;   //接收口设为输入口
   DelayUS(30);
   gR_data=PORTC;
   while(TESTBIT(gR_data,7))  //表示busy
   {
      --gwait_time;
      if(!gwait_time)
      { LCD_EN=0;TRISC = 0x00; return 0; }
   }
    LCD_EN=0;
    TRISC = 0x0;   //恢复为输出口
    return 1;
}
/******************************************************************************
* 函 数 名: Write_LCD_Comd(uint8 commond)
* 函数功能: 写指令
* 入口参数: commond指令
* 返    回: 无
*******************************************************************************/
void Write_1602_command(uchar gcmd,uchar gvalue)
{
   if(gvalue)             //写命令时大部分情况下是在LCD空闲模式下写
   {
      if(Chk_1602_busy())
      {
         LCD_RS=0;         //选择指令
         LCD_RW=0;         //选择写
         PORTC=gcmd;       //赋指令
         LCD_EN=1;         //使能
         DelayUS(30);
         LCD_EN=0;
      }
   }
   else
   {
      LCD_RS=0;         //选择指令
      LCD_RW=0;         //选择写
      PORTC=gcmd;       //赋指令
      LCD_EN=1;         //使能
      DelayUS(30);
      LCD_EN=0;
   }
}
/******************************************************************************
* 函 数 名: Write_LCD_Data(uint8 Data)
* 函数功能: 写数据
* 入口参数: Data数据
* 返    回: 无
*******************************************************************************/
/*----------- 写数据 -------------*/
void Write_1602_data(uchar gdata)
{
   if(Chk_1602_busy())     //写数据必须是在LCD空闲模式下才能写
   {
      LCD_RS=1;             //选择数据
      LCD_RW=0;             //选择写
      PORTC=gdata;
      LCD_EN=1;             //使能
      DelayUS(30);
      LCD_EN=0;
      DelayUS(10);
   }
}
/******************************************************************************
* 函 数 名: LCD1602_Init(void)
* 函数功能: 初始化1602LCD
* 入口参数: 无
* 返    回: 无
*******************************************************************************/
/*-----------1602初始化函数-------------*/
void INIT_1602(void)
{
   Delay_ms(15);
   Write_1602_command(0x38,0);  //设置16X2显示,5X7点阵,8位数据传送,不检测忙信号
   Delay_ms(5);
   Write_1602_command(0x38,0);
   Delay_ms(5);
   Write_1602_command(0x38,0);  //设置16X2显示,5X7点阵,8位数据传送,不检测忙信号
   Write_1602_command(0x38,1);  //设置16X2显示,5X7点阵,8位数据传送,检测忙信号
   Write_1602_command(0x08,1);  //关闭显示、无光标、检测忙信号
   Write_1602_command(0x01,1);  //清屏、光标归位、AC=0、检测忙信号
   Write_1602_command(0x06,1);  //显示光标右移位置、检测忙信号
   Write_1602_command(0x0c,1);  //显示功能开、无光标
}
/******************************************************************************
* 函 数 名: Write_LCD_Mult_Byte(uint8 addr,uint8* pointer,uint8 index,uint8 num)
* 函数功能: 写多字节字符
* 入口参数: addr起始地址,pointer指针地址,index下标,num个数
* 返    回: 无
*******************************************************************************/
/*-----------显示字符串-------------*/
//                                开始地址  行号        数据长度      数组元素
void Display_1602_string(uchar gadd_start,uchar gline,uchar glength,uchar *pdata)
{
   uchar gaddress;
   uchar *pdat;
   uchar gcount=0;
   uchar glongth=glength-gadd_start;  //真正需要写的数据长度
   pdat=pdata+gadd_start;
   if(gline)                          //第0行
   { gaddress=0x80+gadd_start; }      //地址对应
   else
   { gaddress=0xc0+gadd_start; }      //第一行
   for(;gcount<glongth;gcount++)
   {
      Write_1602_command(gaddress,1);        //设定数据地址
      Write_1602_data(*pdat);  //取设定地址里的数据
      gaddress++;
      pdat++;
   }
}
/*-----------指定位置显示字符-------------*/
void Display_1602(uchar x,uchar y,uchar gdata)
{
   uchar gaddress;
   if(y)
   { gaddress=0x80+x; }
   else
   { gaddress=0xc0+x; }
   Write_1602_command(gaddress,1);   //设定数据地址
   Write_1602_data(gdata);
}

/******************************************************************************
* 函 数 名: main()
* 函数功能: LCD显示字符
* 入口参数: 无
* 返    回: 无
*******************************************************************************/
void main()
{
    //ANSEL = 0x00;
    ADCON1 = 0x87;   //设置PORTA为普通IO口
TRISA0 = 0;
TRISA1 = 0;
TRISA2 = 0;
    TRISA3 = 0;
TRISC = 0x00;   //设置PORTC为输出
INIT_1602();
while(1)
{
   Display_1602(0,1,'2');
      
      RA3 = 1;Delay_ms(100);RA3 = 0;
      
      Display_1602_string(0,1,16,tab);
     
      RA3 = 0;Delay_ms(100);RA3 = 1;
}
}


877A和914的工程在PIC_P icject.rar中,使用的是MPLAB和PIC-KIT3。

PIC_Project.rar

54.64 KB

沙发
544852010|  楼主 | 2012-4-17 15:25 | 只看该作者
914单片机的main.c程序:
914单片机的main.c程序:



#include
//#include
//#include
//#include
#define uchar unsigned char
#define uint unsigned int
#define TESTBIT(a,b) ((a)&(1<<(b)))

//__CONFIG(WDTDIS & LVPDIS & HS & PWRTDIS & BORDIS);//设置877配置位
__CONFIG(WDTDIS & HS & PWRTDIS & BORDIS);//设置配置位


#define LCD_RS RA0
#define LCD_RW RA1
#define LCD_EN RA2

/************************定义显示字符*****************************************/

uchar tab[] = {" Welcome T0 Use PIC Study Board "};

/************************声明函数*********************************************/
void DelayUS(uint);
void Delay_ms(uint delay);
uchar Chk_1602_busy(void);
void Write_1602_command(uchar gcmd,uchar gvalue);
void Write_1602_data(uchar gdata);
void INIT_1602(void);
void Display_1602_string(uchar gadd_start,uchar gline,uchar glength,uchar *pdata);
void Display_1602(uchar x,uchar y,uchar gdata);


/*******************************************************************************
* 函 数 名: DelayUS(uint8 delay)
* 函数功能: 微秒延时
* 入口参数: delay
* 返 回: 无
*******************************************************************************/

void DelayUS(uint delay)
{
for(;delay;)
{
NOP();
delay--;
}
}

/*******************************************************************************
* 函 数 名: DelayMS(uint16 delay)
* 函数功能: 毫秒延时
* 入口参数: delay
* 返 回: 无
*******************************************************************************/

void Delay_ms(uint delay)
{
uint i;

for(i=0;i DelayUS(1000);
}

/*******************************************************************************
* 函 数 名: Read_LCD_Busy(void)
* 函数功能: 读液晶忙通道数据
* 入口参数: 无
* 返 回: 无
*******************************************************************************/
uchar Chk_1602_busy(void)
{
uint gR_data;
uint gwait_time=0xff; //设置忙超时数

LCD_RS=0; //表示状态
LCD_RW=1; //选择读
LCD_EN=1;
TRISC = 0xFF; //接收口设为输入口
DelayUS(30);
gR_data=PORTC;

while(TESTBIT(gR_data,7)) //表示busy
{
--gwait_time;
if(!gwait_time)
{ LCD_EN=0;TRISC = 0x00; return 0; }
}

LCD_EN=0;
TRISC = 0x0; //恢复为输出口
return 1;
}

/******************************************************************************
* 函 数 名: Write_LCD_Comd(uint8 commond)
* 函数功能: 写指令
* 入口参数: commond指令
* 返 回: 无
*******************************************************************************/

void Write_1602_command(uchar gcmd,uchar gvalue)
{
if(gvalue) //写命令时大部分情况下是在LCD空闲模式下写
{
if(Chk_1602_busy())
{
LCD_RS=0; //选择指令
LCD_RW=0; //选择写
PORTC=gcmd; //赋指令
LCD_EN=1; //使能
DelayUS(30);
LCD_EN=0;
}
}

else
{
LCD_RS=0; //选择指令
LCD_RW=0; //选择写
PORTC=gcmd; //赋指令
LCD_EN=1; //使能
DelayUS(30);
LCD_EN=0;
}
}

/******************************************************************************
* 函 数 名: Write_LCD_Data(uint8 Data)
* 函数功能: 写数据
* 入口参数: Data数据
* 返 回: 无
*******************************************************************************/

/*----------- 写数据 -------------*/
void Write_1602_data(uchar gdata)
{
if(Chk_1602_busy()) //写数据必须是在LCD空闲模式下才能写
{
LCD_RS=1; //选择数据
LCD_RW=0; //选择写
PORTC=gdata;
LCD_EN=1; //使能
DelayUS(30);
LCD_EN=0;
DelayUS(10);
}
}

/******************************************************************************
* 函 数 名: LCD1602_Init(void)
* 函数功能: 初始化1602LCD
* 入口参数: 无
* 返 回: 无
*******************************************************************************/

/*-----------1602初始化函数-------------*/
void INIT_1602(void)
{
Delay_ms(15);
Write_1602_command(0x38,0); //设置16X2显示,5X7点阵,8位数据传送,不检测忙信号
Delay_ms(5);
Write_1602_command(0x38,0);
Delay_ms(5);
Write_1602_command(0x38,0); //设置16X2显示,5X7点阵,8位数据传送,不检测忙信号
Write_1602_command(0x38,1); //设置16X2显示,5X7点阵,8位数据传送,检测忙信号
Write_1602_command(0x08,1); //关闭显示、无光标、检测忙信号
Write_1602_command(0x01,1); //清屏、光标归位、AC=0、检测忙信号
Write_1602_command(0x06,1); //显示光标右移位置、检测忙信号
Write_1602_command(0x0c,1); //显示功能开、无光标

}

/******************************************************************************
* 函 数 名: Write_LCD_Mult_Byte(uint8 addr,uint8* pointer,uint8 index,uint8 num)
* 函数功能: 写多字节字符
* 入口参数: addr起始地址,pointer指针地址,index下标,num个数
* 返 回: 无
*******************************************************************************/

/*-----------显示字符串-------------*/
// 开始地址 行号 数据长度 数组元素
void Display_1602_string(uchar gadd_start,uchar gline,uchar glength,uchar *pdata)
{
uchar gaddress;
uchar *pdat;
uchar gcount=0;

uchar glongth=glength-gadd_start; //真正需要写的数据长度
pdat=pdata+gadd_start;

if(gline) //第0行
{ gaddress=0x80+gadd_start; } //地址对应
else
{ gaddress=0xc0+gadd_start; } //第一行

for(;gcount {
Write_1602_command(gaddress,1); //设定数据地址
Write_1602_data(*pdat); //取设定地址里的数据
gaddress++;
pdat++;
}
}

/*-----------指定位置显示字符-------------*/
void Display_1602(uchar x,uchar y,uchar gdata)
{
uchar gaddress;

if(y)
{ gaddress=0x80+x; }

else
{ gaddress=0xc0+x; }

Write_1602_command(gaddress,1); //设定数据地址
Write_1602_data(gdata);
}


/******************************************************************************
* 函 数 名: main()
* 函数功能: LCD显示字符
* 入口参数: 无
* 返 回: 无
*******************************************************************************/

void main()
{
ANSEL = 0x00;
//ADCON1 = 0x87; //设置PORTA为普通IO口
TRISA0 = 0;
TRISA1 = 0;
TRISA2 = 0;

TRISA3 = 0;

TRISC = 0x00; //设置PORTC为输出
INIT_1602();
while(1)
{
Display_1602(0,1,'2');

RA3 = 1;Delay_ms(100);RA3 = 0;

Display_1602_string(0,1,16,tab);

RA3 = 0;Delay_ms(100);RA3 = 1;
}
}  
UID136924 帖子11 精华0 威望150  芯币22 枚 阅读权限10 在线时间1 小时 注册时间2009-7-2 最后登录2012-4-17 查看详细资料
TOP↑

使用特权

评论回复
板凳
544852010|  楼主 | 2012-4-17 15:27 | 只看该作者
本来要显示 2  和 welcome to use
在877上就显示正常 877上面显示 2  和 welcome to use
在914上面 就是第一排16个暗黑方块(几乎看不清楚)

两程序的区别在于  1:CONFIG
                           2:877A用ADCON1,914用ANSEL

使用特权

评论回复
地板
电子老鹰| | 2012-4-17 16:08 | 只看该作者
877没用过,但感觉PIC两种型号间差别不大,主要是寄存器和管脚的些微变化。
针对你的问题,我认为应该重点查一下驱动1621的语句中涉及914管脚和寄存器的内容与877有什么差别。

使用特权

评论回复
5
544852010|  楼主 | 2012-4-18 16:34 | 只看该作者
首先,谢谢4楼的建议,我将再仔细检查管脚的寄存器之间的区别。
回复4楼:
在877A上,我使用RA0 1 2 作为1602液晶屏的 DI  R/W  EN  使用 PORTC(RC0-RC7)作为数据端口D0-D7

在913单片机上,依然是这样,未做任何修改

我单片机开发板,有单片机底座,扳起小扳手,可以将877A拿下来,因此,可以切换单片机877A和913,都是40脚的,并且,单片机每一个引脚外,都有调帽引出来,拔掉所有调帽,单片机就成裸机了。

用913时,用RA3点亮LED灯来指示程序是否运行及运行到何处,可以看到,程序依然运行正常。

使用特权

评论回复
6
aresmcu| | 2012-4-20 09:27 | 只看该作者
//        ADCON1 = 0x06;        // Disable analog pins on PORTA 87X
    ANSEL=3;//887 RA0 1端口设置为输入模式

int i;     //定义循环次数控制寄存器   
      GIE=0;//保护ADC采集数据
    //  ad_l=0;// 低8位寄存器值
      ad_h=0;  // 高低8位寄存器值
      
           if(mode==1)
           {ADCON0=0X45;}//FOSC/8  8bit AN1
           if(mode!=1)
           {ADCON0=0X41;}//FOSC/8  8bit AN0
            ADCON1=0;    //左对齐-8bit VSS VDD  0X80-右对齐-10bit
      for(i=5;i>0;i--)          //求5次转换结果的平均值   
     {   
     // ADGO=0X1;              //开启转换过程   87x
      GODONE=0x1;//887
      __delay_us(2);
    //  while(ADGO);           //等待转换完成   87x
      while(GODONE);//887
    //  ad_l=ad_l+ADRESL;  //累计转换结果  
      ad_h=ad_h+ADRESH;  
      }  

这个是我87A移植到887上面时的操作 和你的差不多 要设置ANSEL 我的这一就OK了  配置字我都是软件里设置的

使用特权

评论回复
7
尛舞icc| | 2012-11-28 14:54 | 只看该作者
你电位器接了吗  要调节电位器  才能改变液晶的显示明暗度

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

68

帖子

1

粉丝