搜索
bottom↓
回复: 8

兄弟们帮我看看PIC16F877四线驱动LCD1602问题

[复制链接]

出0入0汤圆

发表于 2009-4-22 11:00:31 | 显示全部楼层 |阅读模式
兄弟们,我的控制线用RB0—RB2驱动正常,为什么换成RE0—RE2就不正常了?四线驱动的下面有程序
#include <pic.h>
//#include <pic1687x.h>
//#define _16F877
__CONFIG (HS & PROTECT & PWRTEN & BOREN & WDTDIS & DEBUGEN);
/******************************************************************************/
#define uint8                   unsigned char
#define int8                    char
#define uint16                  unsigned int
#define int16                   int
#define uint32                  unsigned long
#define int32                   long
/******************************************************************************/
#define LCD_CMD_WR                                                   (1 << 0)
#define LCD_DATA_WR                                                   (1 << 0)
#define LCD_BUSY_RD                                                   (1 << 1)//0x02
#define LCD_DATA_RD                                                   0x03
                     
//LCD Commands        
#define LCD_CLS                                                                   0x01
#define LCD_HOME                                                           0x02
#define LCD_SETMODE                                                   0x04
#define LCD_SETVISIBLE                                   0x08
#define LCD_SHIFT                                                           0x10
#define LCD_SETFUNCTION                                   0x20
#define LCD_SETCGADDR                                           0x40
#define LCD_SETDDADDR                                           0x80
                                          
#define E_PIN_MASK                                 (1 << 2)
/******************************************************************************/
#define DATA_DDR_ON                                                   DATA_DDR&=0x0F// = 0x00
#define DATA_DDR_OFF                                           DATA_DDR|=0xF0// = 0xFF
                                           
#define DATA_PORT_ON                                           DATA_PORT|=0xF0// = 0xFF
#define DATA_PORT_OFF                                           DATA_PORT&=0x0F// = 0x00     
                                           
#define DATA_DDR                                        TRISD     
#define DATA_PORT                                        PORTD
                                              
#define CORTROL_DDR                                        TRISE
#define CORTROL_PORT                                        PORTE
/******************************************************************************/
uint8 flag;
/******************************************************************************/
uint8 pacmanopen[] = {0x0E,0x07,0x03,0x01,0x03,0x07,0x0E,0x00,'\n'};
uint8 pacmanshut[] = {0x00,0x0F,0x1F,0x01,0x1F,0x0F,0x00,0x00,'\n'};
uint8 text[] = {'4','-','B','i','t',' ','L','C','D',' ','M','o','d','e', ' ','\n'};
/*************************************************************/
void delay_us (uint16 disp_time) //
{
        do
        {
                   disp_time--;
           }
        while(disp_time>0);
}
/*************************************************************/
void delay_ms (uint16 disp_time)
{
        while(disp_time>0)
        {
                delay_us(1000);
                disp_time--;
          }
}
/*************************************************************/
void wrcmd (uint8 cmdcode)
{
                //lcd_wait();
        DATA_DDR&=0x0F;
        DATA_PORT&=0x0F;
           DATA_PORT |= (cmdcode & 0xF0);                          // Get the most significant nibble first.
    //CORTROL_PORT = CORTROL_DDR = 0;
           CORTROL_DDR &= ~(1 << 0);
           CORTROL_DDR &= ~(1 << 1);
           CORTROL_DDR &= ~(1 << 2);
          
           CORTROL_PORT &= ~(1 << 0);
           CORTROL_PORT &= ~(1 << 1);
           CORTROL_PORT &= ~(1 << 2);          
          
          
           CORTROL_PORT &= ~LCD_CMD_WR;                               // Specify a command write operation.
           CORTROL_PORT |= E_PIN_MASK;                               // Toggle the 'E' pin to send the command.
           asm("NOP");asm("NOP");asm("NOP");
           CORTROL_PORT &= ~E_PIN_MASK;
          
           DATA_DDR&=0x0F;
           DATA_PORT&=0x0F;
           DATA_PORT |= ((cmdcode << 4)&0xF0);                     // Repeat for least significant nibble.
           CORTROL_PORT &= ~LCD_CMD_WR;
           CORTROL_PORT |= E_PIN_MASK;
           asm("NOP");asm("NOP");asm("NOP");
           CORTROL_PORT &= ~E_PIN_MASK;         
                                            // Call the wait routine.
}
/*************************************************************/     
void wrdata (uint8 data)
{
                //lcd_wait();
        DATA_DDR&=0x0F;
        DATA_PORT&=0x0F;
           DATA_PORT |= (data & 0xF0);                         // Get the most significant nibble first.
           //CORTROL_PORT = LCD_DATA_WR;                         // Specify a data write operation.
           CORTROL_PORT |= (1 << 0);
           CORTROL_PORT &= ~(1 << 1);
           CORTROL_PORT &= ~(1 << 2);
           CORTROL_PORT |= E_PIN_MASK;                         // Toggle the 'E' pin to send the command.
           asm("NOP");asm("NOP");asm("NOP");
           CORTROL_PORT &= ~E_PIN_MASK;
          
           DATA_DDR&=0x0F;
           DATA_PORT&=0x0F;
           DATA_PORT |= ((data << 4)&0xF0);                         // Repeat for least significant nibble.
           //CORTROL_PORT = LCD_DATA_WR;
           CORTROL_PORT |= (1 << 0);
           CORTROL_PORT &= ~(1 << 1);
           CORTROL_PORT &= ~(1 << 2);
           CORTROL_PORT |= E_PIN_MASK;
           asm("NOP");asm("NOP");asm("NOP");
           CORTROL_PORT &= ~E_PIN_MASK;                                          // Call the wait routine.
}
/******************************************************************************/
void lcd_set_xy( uint8 x, uint8 y )  //写地址函数
{
    uint8 address;
    if (y == 0)
    {
             address = 0x80 + x;
           }
    else if (y == 1)
    {
            address = 0xc0 + x;
    }
    else if (y == 2)
    {
            address = 0x94 + x;
    }
    else
    {
            address = 0xD4 + x;
    }
    wrcmd( address);
}
/******************************************************************************/
void lcd_write_onechar(uint8 X1,uint8 Y1,uint8 data) //列x=0~15,行y=0,1
{
          lcd_set_xy( X1, Y1 ); //写地址
          wrdata(data);
}
/*************************************************************/
void lcd_init ()
{
                 DATA_DDR_ON;
                 DATA_PORT_ON;
                  
          //wrcmd(0x28);   
           wrcmd(0x28);
           wrcmd(0x28);
          wrcmd(0x0c);
          wrcmd(0x01);
}
/*************************************************************/  
void LCD_write_string(uint8 X,uint8 Y,uint8 *s) //列x=0~15,行y=0,1
{
    lcd_set_xy( X, Y ); //写地址   
    while (*s)  // 写显示字符
    {
      wrdata( *s );
      s ++;
    }
      
}
/******************************************************************************/
void main(void)  
{  
                ADCON1=0x87;       //转换结果右移,及ADRESH 寄存器的高6 位为"0"
   
           lcd_init();                             // Initialise the LCD Display
           lcd_write_onechar(0,1,0x38);
          for (;;)                                // Loop Forever.
          {       
                   lcd_write_onechar(0,1,0x38);
                   LCD_write_string(0,0,text);
   }  
}
/******************************************************************************/

出0入0汤圆

 楼主| 发表于 2009-4-22 11:10:20 | 显示全部楼层
用RE口的时候我已经把RE口设为数字IO口了, ADCON1=0x87;
我用的是PIC16F877,兄弟们帮我支支招是怎么回事。把控制口换为RB0-RB2显示就正常。

出0入0汤圆

 楼主| 发表于 2009-4-22 11:17:40 | 显示全部楼层
为了兄弟们好看,我重新调整一下程序格式。



#include <pic.h>
__CONFIG (HS & PROTECT & PWRTEN & BOREN & WDTDIS & DEBUGEN);
/******************************************************************************/
#define uint8                   unsigned char
#define int8                    char
#define uint16                  unsigned int
#define int16                   int
#define uint32                  unsigned long
#define int32                   long
/******************************************************************************/
#define LCD_CMD_WR                                          (1 << 0)
#define LCD_DATA_WR                                         (1 << 0)
#define LCD_BUSY_RD                                          (1 << 1)
#define LCD_DATA_RD                                          0x03
                     
//LCD Commands         
#define LCD_CLS                                               0x01
#define LCD_HOME                                               0x02
#define LCD_SETMODE                                           0x04
#define LCD_SETVISIBLE                                        0x08
#define LCD_SHIFT                                             0x10
#define LCD_SETFUNCTION                                       0x20
#define LCD_SETCGADDR                                         0x40
#define LCD_SETDDADDR                                         0x80
                                            
#define E_PIN_MASK                                            (1 << 2)
/******************************************************************************/
#define DATA_DDR_ON                                            DATA_DDR&=0x0F// = 0x00
#define DATA_DDR_OFF                                           DATA_DDR|=0xF0// = 0xFF
                                             
#define DATA_PORT_ON                                           DATA_PORT|=0xF0// = 0xFF
#define DATA_PORT_OFF                                          DATA_PORT&=0x0F// = 0x00      
                                             
#define DATA_DDR                                               TRISD      
#define DATA_PORT                                              PORTD
                                                
#define CORTROL_DDR                                            TRISE
#define CORTROL_PORT                                            PORTE
/******************************************************************************/
uint8 flag;
uint8 text[] = {'4','-','B','i','t',' ','L','C','D',' ','M','o','d','e', ' ','\n'};
/*************************************************************/
void delay_us (uint16 disp_time) //
{
        do
         {
             disp_time--;
         }
         while(disp_time>0);
}
/*************************************************************/
void delay_ms (uint16 disp_time)
{  
        while(disp_time>0)
        {
                delay_us(1000);
                disp_time--;
          }
}  
/*************************************************************/
void wrcmd (uint8 cmdcode)
{  

        DATA_DDR&=0x0F;
        DATA_PORT&=0x0F;
        DATA_PORT |= (cmdcode & 0xF0);                          // Get the most significant nibble first.

           CORTROL_DDR &= ~(1 << 0);
           CORTROL_DDR &= ~(1 << 1);
           CORTROL_DDR &= ~(1 << 2);
            
           CORTROL_PORT &= ~(1 << 0);
           CORTROL_PORT &= ~(1 << 1);
           CORTROL_PORT &= ~(1 << 2);            
            
            
           CORTROL_PORT &= ~LCD_CMD_WR;                               // Specify a command write operation.
           CORTROL_PORT |= E_PIN_MASK;                               // Toggle the 'E' pin to send the command.
           asm("NOP");asm("NOP");asm("NOP");
           CORTROL_PORT &= ~E_PIN_MASK;
            
           DATA_DDR&=0x0F;
           DATA_PORT&=0x0F;
           DATA_PORT |= ((cmdcode << 4)&0xF0);                     // Repeat for least significant nibble.
           CORTROL_PORT &= ~LCD_CMD_WR;
           CORTROL_PORT |= E_PIN_MASK;
           asm("NOP");asm("NOP");asm("NOP");
           CORTROL_PORT &= ~E_PIN_MASK;           
}
/*************************************************************/      
void wrdata (uint8 data)
{
        DATA_DDR&=0x0F;
        DATA_PORT&=0x0F;
        DATA_PORT |= (data & 0xF0);                         // Get the most significant nibble first.  
        CORTROL_PORT |= (1 << 0);
        CORTROL_PORT &= ~(1 << 1);
        CORTROL_PORT &= ~(1 << 2);
        CORTROL_PORT |= E_PIN_MASK;                         // Toggle the 'E' pin to send the command.
        asm("NOP");asm("NOP");asm("NOP");
        CORTROL_PORT &= ~E_PIN_MASK;
            
           DATA_DDR&=0x0F;
           DATA_PORT&=0x0F;
           DATA_PORT |= ((data << 4)&0xF0);                         // Repeat for least significant nibble.
           //CORTROL_PORT = LCD_DATA_WR;
           CORTROL_PORT |= (1 << 0);
           CORTROL_PORT &= ~(1 << 1);
           CORTROL_PORT &= ~(1 << 2);
           CORTROL_PORT |= E_PIN_MASK;
           asm("NOP");asm("NOP");asm("NOP");
           CORTROL_PORT &= ~E_PIN_MASK;                                          // Call the wait routine.
}
/******************************************************************************/
void lcd_set_xy( uint8 x, uint8 y )  //写地址函数
{
    uint8 address;
    if (y == 0)
    {
             address = 0x80 + x;
           }
    else if (y == 1)
    {  
            address = 0xc0 + x;
    }
    else if (y == 2)
    {  
            address = 0x94 + x;
    }
    else  
    {  
            address = 0xD4 + x;
    }
    wrcmd( address);
}
/******************************************************************************/  
void lcd_write_onechar(uint8 X1,uint8 Y1,uint8 data) //列x=0~15,行y=0,1
{
      lcd_set_xy( X1, Y1 ); //写地址
      wrdata(data);
}
/*************************************************************/
void lcd_init ()  
{  
     DATA_DDR_ON;
      DATA_PORT_ON;     
      wrcmd(0x28);  
      wrcmd(0x28);  
      wrcmd(0x0c);
      wrcmd(0x01);
}
/*************************************************************/   
void LCD_write_string(uint8 X,uint8 Y,uint8 *s) //列x=0~15,行y=0,1
{
    lcd_set_xy( X, Y ); //写地址     
    while (*s)  // 写显示字符
    {
      wrdata( *s );
      s ++;
    }
      
}
/******************************************************************************/  
void main(void)   
{   
      ADCON1=0x87;       //转换结果右移,及ADRESH 寄存器的高6 位为"0"
   
      lcd_init();                             // Initialise the LCD Display  
      lcd_write_onechar(0,1,0x38);
      for (;;)                                // Loop Forever.  
      {         
          lcd_write_onechar(0,1,0x38);
          LCD_write_string(0,0,text);
      }   
}
/******************************************************************************/

出0入0汤圆

 楼主| 发表于 2009-4-22 13:21:40 | 显示全部楼层
ding

出0入90汤圆

发表于 2009-4-22 13:36:32 | 显示全部楼层
RE口,你的RE口的AD部分禁止了没?默认RA,RE口都是模拟io的!

出0入0汤圆

 楼主| 发表于 2009-4-22 13:58:05 | 显示全部楼层
我已经禁止为A、D口了啊。 ADCON1=0x87;

出0入0汤圆

 楼主| 发表于 2009-4-22 14:00:24 | 显示全部楼层
我试过了,用RC0-RC1也不行,以上程序在不做任何修改的情况下只有RB0—RB2和RD0-RD2正确。兄弟们看看是不是我程序有漏洞,还哪没设置正确?

出0入4汤圆

发表于 2009-4-23 00:30:22 | 显示全部楼层
#define DPORT          PORTB        // 定义数据端口为B端口
#define DTRIS          TRISB                // 定义数据端口的方向
#define CTRIS_E  TRISC0        // 定义端口的方向
#define CTRIS_RS TRISC1        // 定义端口的方向
#define RS    RC1       
#define E     RC0

void LCD_WriteComm(unsigned int TheComm){
// 定义向LCD写一个指令字的函数
        CTRIS_RS = 0;                // 定义端口为写状态
        CTRIS_E = 0;               
        DTRIS = 0x00;               
        DPORT = TheComm;        // 把数据输出到端口,实际上只是高4位
        RS    = 0;
        E     = 0;
        E     = 0;                        // 多了一个指令,是为了让信号电平有足够得时间稳定
        E     = 1;
        DPORT = TheComm<<4;        // 将数据的低4位移位到高4位,输出到端口
        RS    = 0;
        E     = 0;
        E     = 0;
        E     = 1;
}

void LCD_WriteDate(unsigned int Hang,unsigned int No,unsigned char TheDate){
// 定义向LCD的第Hang行的第No个位置,写字符TheDate
// Hang:0,1; No:0-15;
        unsigned char tmpi;
        tmpi = Hang*0x40+No+0x80;        // 计算地址指针
        LCD_NoBusy();
        CTRIS_RS = 0;               
        CTRIS_E = 0;               
        DTRIS = 0x00;               
        DPORT = tmpi;
        RS    = 0;
        E     = 0;
        E     = 0;
        E     = 1;
        DPORT = tmpi<<4;
        E     = 0;
        E     = 0;
        E     = 1;
       
        LCD_NoBusy();
        DTRIS = 0x00;                       
        DPORT = TheDate;
        RS    = 1;               
        E     = 0;
        E     = 0;
        E     = 1;
        DPORT = TheDate<<4;
        E     = 0;
        E     = 0;
        E     = 1;
}

void LCD_NoBusy(){
        delay(2);
}

void LCD_init()
// 初始化LCD显示屏
{
       
        delay(20);                        //1、延时大约20ms
        CTRIS_RS = 0;               
        CTRIS_E = 0;               
        DTRIS = 0x00;               
        DPORT = 0x30;
        RS    = 0;               
        E     = 0;
        E     = 0;
        E     = 1;
        delay(5);               
        DPORT = 0x30;
        RS    = 0;               
        E     = 0;
        E     = 0;
        E     = 1;
        delay(2);               
        DPORT = 0x30;
        RS    = 0;               
        E     = 0;
        E     = 0;
        E     = 1;
        delay(2);               
        DPORT = 0x20;
        RS    = 0;               
        E     = 0;
        E     = 0;
        E     = 1;
        delay(2);               

        LCD_WriteComm(0x28);       
        delay(4);
        LCD_WriteComm(0x08);        //4、写指令08H,关闭LCD       
        LCD_NoBusy();
        LCD_WriteComm(0x01);        //5、写指令01H,清屏LCD
        LCD_NoBusy();
        LCD_WriteComm(0x06);        //6、写指令06H
        LCD_NoBusy();
        LCD_WriteComm(0x0C);        //7、写指令0CH
};
这个是实测能用的。PIC16F877A,

出0入4汤圆

发表于 2009-4-23 00:31:30 | 显示全部楼层
R/W接地了的,不检测LCD是否忙碌。加延时去解决。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-9 08:28

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表