Gorgon_Meducer 发表于 2005-9-12 18:34:20

[分享][2008-6-13 update]一些关于1602显示的头文件

RD_LCD1602b.c
/***********************************************************
*   函数库说明:LCD1602B基本驱动函数库                     *
*   版本:      v2.11                                    *
*   作者:      傻孩子                                     *
*   创建日期:2005年9月6日                               *
* -------------------------------------------------------- *
*[支 持 库]                                              *
* -------------------------------------------------------- *
*[版本更新]                                              *
*   修改:      傻孩子                                     *
*   修改日期:2006年6月8日                               *
*   版本:      v2.11                                    *
* -------------------------------------------------------- *
*[版本历史]                                              *
* -------------------------------------------------------- *
*[使用说明]                                              *
*            1、需要底层硬件驱动函数支持               *
*               基本的宏定义:                           *
*               LCD_RS   LCD_RW   LCD_E                  *
*               LCD_SET_WRITE_DATALCD_SET_READ_DATA    *
*               LCD_SEND_HALF_CHAR_HIGH(a)               *
*               LCD_SEND_HALF_CHAR_LOW(a)                *
*               当处于串行状态下时,只定义LCD_RS         *
*               LCD_E LCD_SEND_HALF_CHAR_HIGH(a)         *
*               LCD_SEND_HALF_CHAR_LOW(a)                *
*            2、如果采用8数据位连接,则需要定义数据端口*
*               LCD_DATA_PORT,同时需要定义宏来开启该功*
*               能:_LCD1602_FULL_DATA_MODEL             *
*            3、需要修改引用宏定义来指定底层硬件驱动   *
*               函数库。                                 *
*            4、本库驱动下的LCD显示支持1602的各种连      *
*               接方法。当使用只写模式是请在引用该头   *
*               文件之前加上宏定义:                     *
*               # define _USE_LCD_ONLY_WRITE             *
*            5、在调用本库之前,定义RunStringSpeed可   *
*               以设置滚屏的速度。通过在引用前定义       *
*               FlashTimeOut 和 FlashGIFTimeOut 可以   *
*               改变字符闪烁的频率。                     *
*            6、增加一个GIF字幕特效函数。                *
*            7、确定没有LCD复位问题。                  *
*            8、增加对595串行转并行连接的支持。          *
*               需要头文件SerialToCollateral.h         *
***********************************************************/

/********************
* 头 文 件 配 置 区 *
********************/
# include "RD_MacroAndConst.h"
# include "LIB_Config.h"
# include "RD_LCD1602B.h"


/********************
*   系 统 宏 定 义*
********************/

/*------------------*
*   常 数 宏 定 义*
*------------------*/
# define LCD_CMD_DISP_CTR   0x0c
# define LCD_CMD_CLS      0x01
# define LCD_CMD_ENTER_SET0x02
# define LCD_CMD_ICON_SHOW0x0f
# define LCD_CMD_ICON_HIDE0x0c
# define LCD_CMD_NOT_MOVE   0x14


# define LCD_WRITE          0x00
# define LCD_READ         0x01
# define LCD_COMMAND      0x00
# define LCD_DATA         0x01

#ifndef LCD_RUN_STRING_SPEED
    # define LCD_RUN_STRING_SPEED 100
#endif

#ifndef LCD_FLASH_TIME_OUT
    # define LCD_FLASH_TIME_OUT   0x03ff
#endif
#ifndef LCD_FLASH_STRING_GROUP_TIME_OUT
    # define LCD_FLASH_STRING_GROUP_TIME_OUT0x03ff
#endif

/*------------------*
*   动 作 宏 定 义*
*------------------*/

#if defined(_USE_LCD_ONLY_WRITE) || defined(_Use_LCD1602B_Serial)
    #ifndef LCD_SET_WRITE_DATA
      # define LCD_SET_WRITE_DATA
    #endif
    #ifndef LCD_SET_READ_DATA
      # define LCD_SET_READ_DATA
    #endif
    #ifndef LCD_RW
      # define LCD_RW   LCD_Temp
    #endif
   
    #ifndef LCD_BF
          # define LCD_BF   LCD_Temp
    #endif
#else
    #ifndef LCD_SET_WRITE_DATA
      # error No define LCD_SET_WRITE_DATA
    #endif
    #ifndef LCD_SET_READ_DATA
      # error No define LCD_SET_READ_DATA
    #endif
    #ifndef LCD_RW
      # error No define LCD_RW
    #endif
    #ifndef LCD_BF
          # error No define LCD_BF
    #endif
#endif

#ifndef LCD_RS
    # error Need define LCD_RS
#endif

#ifndef _Use_LCD1602B_Serial
    # define SetReadState       LCD_SET_READ_DATA;LCD_RS = LCD_COMMAND;LCD_RW = LCD_READ;
    # define SetRead            LCD_SET_READ_DATA;LCD_RW = LCD_READ;
    # define SetWrite         LCD_SET_WRITE_DATA;LCD_RW = LCD_WRITE;
    # define SetCommand         LCD_RS = LCD_COMMAND;
    # define SetData            LCD_RS = LCD_DATA;
#else
    # define _USE_LCD_ONLY_WRITE
    # define SetReadState
        # define SetRead
        # define SetWrite
        # define SetCommand         LCD_RS = LCD_COMMAND;refreshVirtualPORT();
        # define SetData            LCD_RS = LCD_DATA;refreshVirtualPORT();   
        # define SetEnable          LCD_E = High;refreshVirtualPORT();
        # define SetDisable         LCD_E = Low;refreshVirtualPORT();
#endif

#ifdef _LCD1602_FULL_DATA_MODEL
    #ifndef LCD_DATA_PORT
      #error Need for macro: LCD_DATA_PORT
    #endif
#endif
/********************
*用户变量类型定义 *
********************/

/********************
*模块结构体定义区 *
********************/

/********************
*   模块函数声明区*
********************/
static void LCDDelay(UINT16 Time);
static void LCDDelayUs(UINT16 Time);


/********************
*   全局函数声明区*
********************/
void LCDInit(void);
void LCDSetXY(UINT8 X,UINT8 Y);
void LCDDisplayString(UINT8 *String);
void LCDDisplayNum(unsigned long Num,UINT8 BitCount);
void RunString(UINT8 *String,UINT8 Y,UINT8 StartX,UINT8 EndX);
UINT8 StringLength(UINT8 *String);
void Flash(UINT8 *String,UINT8 Icon,UINT8 X,UINT8 Y);
void FlashStringGroup(UINT8 String[],UINT8 StringCounter,UINT8 X,UINT8 Y);
void LCDWaitForReady(void);
void LCDSendCommand(UINT8 Command);
void LCDSendData(UINT8 Data);
void PrintD(INT32 nNumber,UINT8 chCounter);

/********************
*   全局函数引用区*
********************/
#ifdef _Use_LCD1602B_Serial
    extern void refreshVirtualPORT(void);
#endif

/********************
*   模块变量声明区*
********************/
const static UINT8 CHR = {'0','1','2','3','4','5','6','7','8'
                     ,'9','a','b','c','d','e','f'};
                     
/********************
*   全局变量声明区*
********************/
static UINT8 LCD_Temp = 0;

/********************
*   全局变量引用区*
********************/
#ifndef SYS_TIMER_MS_ADD_UNTILL_OVF
extern UINT16 g_wSystemTimer;
    #define SYS_TIMER_MS_ADD_UNTILL_OVF g_wSystemTimer
#else
extern UINT16 SYS_TIMER_MS_ADD_UNTILL_OVF;
#endif



/***********************************************************
*   函数说明:LCD驱动类毫秒延时函数                        *
*   输入:    需要延时的大体毫秒数                         *
*   输出:    无                                           *
*   调用函数:LCDDelayUs()                                 *
***********************************************************/
static void LCDDelay(UINT16 Time)
{
    UINT16 TimeCounter = 0;
       
        for (TimeCounter = 0;TimeCounter < Time;TimeCounter ++)
        {
          LCDDelayUs(255);
        }
}

/***********************************************************
*   函数说明:LCD驱动指令周期延时函数                      *
*   输入:    需要大体延时Us数                           *
*   输出:    无                                           *
*   调用函数:无                                           *
***********************************************************/
static void LCDDelayUs(UINT16 Time)
{
   UINT16 TimeCounter = 0;
       for (TimeCounter = 0;TimeCounter < Time;TimeCounter ++)
       {
             asm("nop");
       }
}

/***********************************************************
*   函数说明:LCD初始化函数                              *
*   输入:    无                                           *
*   输出:    无                                           *
*   调用函数:LCDDelay()LCDWaitForReady()                *
*             LCDSendCommand()                           *
***********************************************************/
void LCDInit(void)
{
    LCDDelay(15);
   
#ifndef _LCD1602_FULL_DATA_MODEL
        LCDSendCommand(0x28);
#else
    LCDSendCommand(0x38);
#endif
    //LCDWaitForReady();
    LCDDelay(100);
        LCDSendCommand(LCD_CMD_DISP_CTR);
    LCDDelay(100);
        LCDSendCommand(LCD_CMD_CLS);
        LCDDelay(100);
        LCDSendCommand(LCD_CMD_ENTER_SET);
    LCDDelay(100);
    LCDSendCommand(LCD_CMD_NOT_MOVE);
       
}

#ifndef _Use_LCD1602B_Serial
/***********************************************************
*   函数说明:向LCD发送指令函数                            *
*   输入:    需要发送的指令                               *
*   输出:    无                                           *
*   调用函数:LCD_SEND_HALF_CHAR_HIGH() LCD_SEND_HALF_CHAR_LOW() *
***********************************************************/
void LCDSendCommand(UINT8 Command)
{
        SetWrite;
        SetCommand;
    #ifndef _LCD1602_FULL_DATA_MODEL
        {
                LCD_SEND_HALF_CHAR_HIGH(Command);
      LCD_E = HIGH;
          LCD_E = LOW;
        }
        {
      LCD_SEND_HALF_CHAR_LOW(Command);       
                LCD_E = HIGH;
                LCD_E = LOW;
        }
    #else
      LCD_DATA_PORT = Command;
      LCD_E = HIGH;
      LCD_E = LOW;
    #endif
    SetRead;               
        SetCommand;
}

/***********************************************************
*   函数说明:向LCD发送数据函数                            *
*   输入:    需要发送的数据                               *
*   输出:    无                                           *
*   调用函数:LCD_SEND_HALF_CHAR_HIGH() LCD_SEND_HALF_CHAR_LOW() *
***********************************************************/
void LCDSendData(UINT8 Data)
{
    SetWrite;
        SetData;
    #ifndef _LCD1602_FULL_DATA_MODEL
        {
                LCD_SEND_HALF_CHAR_HIGH(Data);
                LCD_E = HIGH;
          LCD_E = LOW;
        }

        {
      LCD_SEND_HALF_CHAR_LOW(Data);       
                LCD_E = HIGH;
                LCD_E = LOW;
        }
    #else
      LCD_DATA_PORT = Data;
      LCD_E = HIGH;
      LCD_E = LOW;
    #endif
    SetRead;               
        SetCommand;
}

/***********************************************************
*   函数说明:等待LCD空闲状态函数                        *
*   输入:    无                                           *
*   输出:    无                                           *
*   调用函数:LCDDelayUs()                                 *
***********************************************************/
void LCDWaitForReady(void)
{
#ifdef _USE_LCD_ONLY_WRITE
        LCDDelayUs(500);
#else
       
        SetRead;
        SetCommand;
   
    LCD_E = HIGH;
        while (LCD_BF == 1);   //RW=1,读PD7,为0表示空闲;
    LCD_E = LOW;
       
#endif
}
#else

/***********************************************************
*   函数说明:向LCD发送指令函数                            *
*   输入:    需要发送的指令                               *
*   输出:    无                                           *
*   调用函数:LCD_SEND_HALF_CHAR_HIGH()                  *
*             LCD_SEND_HALF_CHAR_LOW()                     *
***********************************************************/
void LCDSendCommand(UINT8 Command)
{
        SetCommand;
        {
          SetEnable;
               
                LCD_SEND_HALF_CHAR_HIGH(Command);
               
          SetDisable;
        }
        {
          SetEnable;
               
      LCD_SEND_HALF_CHAR_LOW(Command);       
               
                SetDisable;
        }
        SetCommand;
}

/***********************************************************
*   函数说明:向LCD发送数据函数                            *
*   输入:    需要发送的数据                               *
*   输出:    无                                           *
*   调用函数:LCD_SEND_HALF_CHAR_HIGH()                  *
*             LCD_SEND_HALF_CHAR_LOW()                     *
***********************************************************/
void LCDSendData(UINT8 Data)
{
   
        SetData;
        {
          SetEnable;
               
                LCD_SEND_HALF_CHAR_HIGH(Data);
               
          SetDisable;
        }

        {
          SetEnable;
               
      LCD_SEND_HALF_CHAR_LOW(Data);       
               
                SetDisable;
        }
        SetCommand;
}

/***********************************************************
*   函数说明:等待LCD空闲状态函数                        *
*   输入:    无                                           *
*   输出:    无                                           *
*   调用函数:LCDDelayUs()                                 *
***********************************************************/
void LCDWaitForReady(void)
{
        LCDDelayUs(30);
}

#endif


/***********************************************************
*   函数说明:设置显示坐标函数                           *
*   输入:    x,y坐标值                                    *
*   输出:    无                                           *
*   调用函数:LCDWaitForReady()LCDSendCommand()          *
***********************************************************/
void LCDSetXY(UINT8 X,UINT8 Y)
{
    UINT8 Address;
    if (Y == 0)
        {
          Address = 0x80 + X;
        }
    else
        {
      Address = 0xc0 + X;
        }
       
        LCDWaitForReady();
    LCDSendCommand(Address);
}

/***********************************************************
*   函数说明:LCD字符串显示函数                            *
*   输入:    要显示的字符串指针                           *
*   输出:    无                                           *
*   调用函数:LCDWaitForReady() LCDSendData()            *
***********************************************************/
void LCDDisplayString(UINT8 *String)
{
    while(*String)
        {
          LCDWaitForReady();
          LCDSendData(*String);
                String++;
        }
}

/***********************************************************
*   函数说明:数值显示函数(HEX)                            *
*   输入:    需要显示的数字(无符号长整形)               *
*   输出:    无                                           *
*   调用函数:LCDSendData()                              *
***********************************************************/
void LCDDisplayNum(unsigned long Num,UINT8 BitCount)
{
    UINT8 a = 0;
        for (a = 8-BitCount ;a<8;a++)
        {
      LCDWaitForReady();
          LCDSendData(CHR[(Num<<(a<<2))>>28]);
        }
}


/***********************************************************
*   函数说明:滚屏字幕效果                                 *
*   输入:    需要滚屏的字符串 长度 位置                   *
*   输出:    无                                           *
*   调用函数:LOCATE()   PRINT()                           *
***********************************************************/
void RunString(UINT8 *String,UINT8 Y,UINT8 StartX,UINT8 EndX)
{
   
    static UINT8 StringHead = 0;
    UINT8 SCREEN;
    UINT8 a = 0;
    UINT8 Point = StringHead;
    UINT8 StringLong = StringLength(String);
    static UINT16 RunTimeCounter = 0;
       
    for (a = 0;a<EndX - StartX + 1;a++)
        {
      SCREEN = String;
      Point ++;
      if (Point == StringLong)
      {
            Point = 0;
      }
    }
       
    for (;a < 17;a++)
        {
          SCREEN = 0;
        }
       
        RunTimeCounter ++;
        if (RunTimeCounter > LCD_RUN_STRING_SPEED)
        {
          StringHead ++;
                RunTimeCounter = 0;
                if (StringHead == StringLong)
          {
                StringHead = 0;
          }
        }
       
        LOCATE(StartX,Y)
        PRINT(SCREEN)
}

/***********************************************************
*   函数说明:字符串长度测试函数                           *
*   输入:    字符串指针                                 *
*   输出:    字符串的长度                                 *
*   调用函数:无                                           *
***********************************************************/
UINT8 StringLength(UINT8 *String)
{
    UINT8 n = 0;
        while (*String)
        {
          n++;
                String ++;
        }
       
        return n;
}

/***********************************************************
*   函数说明:闪烁显示函数                                 *
*   输入:    要显示的字符串、显示的光标、x,y坐标位置      *
*   输出:    无                                           *
*   调用函数:LOCATE()LCDWaitForReady() LCDSendData()    *
***********************************************************/

void Flash(UINT8 *String,UINT8 Icon,UINT8 X,UINT8 Y)
{
    UINT8 a = 0;
        UINT8 StringLong = StringLength(String);
       
    if ((SYS_TIMER_MS_ADD_UNTILL_OVF & LCD_FLASH_TIME_OUT)
      > (LCD_FLASH_TIME_OUT >> 1))
        {
          LOCATE(X,Y)
                PRINT(String)   
        }
        else
        {
          for (a = X;a < (X+StringLong);a++)
                {
                  LOCATE(a,Y)
                        LCDWaitForReady();
                        LCDSendData(Icon);
                }
        }
}

/***********************************************************
*   函数说明:字幕GIF函数                                  *
*   输入:    要显示的字符串集合指针,字符串数目,位置   *
*   输出:    无                                           *
*   调用函数:LOCATE()PRINT()                            *
***********************************************************/
void FlashStringGroup(UINT8 String[],UINT8 StringCounter,UINT8 X,UINT8 Y)
{
    static UINT8 Pictures = 0;
        static UINT8 DispState = 0;
    if ((SYS_TIMER_MS_ADD_UNTILL_OVF & LCD_FLASH_STRING_GROUP_TIME_OUT)
      > (LCD_FLASH_STRING_GROUP_TIME_OUT >> 1))
        {
          if (DispState == 0)
                {
                Pictures ++;
                  if (Pictures == StringCounter)
                  {
                        Pictures = 0;
                  }
                        DispState = 1;
                }
        }
        else
        {
          if (DispState == 1)
                {
                  Pictures ++;
                        if (Pictures == StringCounter)
                        {
                          Pictures = 0;
                        }
                        DispState = 0;
                }
        }
       
        LOCATE(X,Y);
        PRINT(String);
}


/***********************************************************
*   函数说明:数值显示函数                                 *
*   输入:    要显示的整数                                 *
*   输出:    无                                           *
*   调用函数:无                                           *
***********************************************************/
void PrintD(INT32 nNumber,UINT8 chCounter)
{
    uint8 cTempBuff = {0};
    uint8 n = 0;
    uint32 wTempNumber = ABS(nNumber);
    BOOLbIfFindFirstNoneZeroNumber = FALSE;
   
    if (nNumber < 0)
    {
      PRINT("-")
    }
    else
    {
      PRINT(" ")
    }
   
    for (n = 9;n > 0;n--)
    {
      cTempBuff = (wTempNumber % 10);
      wTempNumber /= 10;
    }
   
    if (chCounter)
    {
      bIfFindFirstNoneZeroNumber = TRUE;
    }
    else
    {
      chCounter = UBOUND(cTempBuff);
      bIfFindFirstNoneZeroNumber = FALSE;
    }
   
    chCounter = MIN(chCounter,UBOUND(cTempBuff));
   
    for (n = UBOUND(cTempBuff) - chCounter;n < UBOUND(cTempBuff);n++)
    {
      if (cTempBuff)
      {
            PRINTN(cTempBuff,1);

            bIfFindFirstNoneZeroNumber = TRUE;
      }
      else if (bIfFindFirstNoneZeroNumber)
      {
            PRINTN(cTempBuff,1);

      }
    }
   
    if (!bIfFindFirstNoneZeroNumber)
    {
      PRINTN(0,chCounter);
    }
   
}

RD_LCD1602b.h
#ifndef _Use_LCD1602B
#define _Use_LCD1602B
/***********************************************************
*   声明库说明:LCD1602B基本驱动函数声明库               *
*   版本:      v2.11                                    *
*   作者:      傻孩子                                     *
*   创建日期:2005年9月6日                               *
* -------------------------------------------------------- *
*[支 持 库]                                              *
* -------------------------------------------------------- *
*[版本更新]                                              *
*   修改:      傻孩子                                     *
*   修改日期:2006年6月8日                               *
*   版本:      v2.11                                    *
* -------------------------------------------------------- *
*[版本历史]                                              *
* -------------------------------------------------------- *
*[使用说明]                                              *
*            1、需要底层硬件驱动函数支持               *
*               基本的宏定义:                           *
*               LCD_RS   LCD_RW   LCD_E                  *
*               LCD_SET_WRITE_DATALCD_SET_READ_DATA    *
*               LCD_SEND_HALF_CHAR_HIGH(a)               *
*               LCD_SEND_HALF_CHAR_LOW(a)                *
*               当处于串行状态下时,只定义LCD_RS         *
*               LCD_E LCD_SEND_HALF_CHAR_HIGH(a)         *
*               LCD_SEND_HALF_CHAR_LOW(a)                *
*            2、如果采用8数据位连接,则需要定义数据端口*
*               LCD_DATA_PORT,同时需要定义宏来开启该功*
*               能:_LCD1602_FULL_DATA_MODEL             *
*            3、需要修改引用宏定义来指定底层硬件驱动   *
*               函数库。                                 *
*            4、本库驱动下的LCD显示支持1602的各种连      *
*               接方法。当使用只写模式是请在引用该头   *
*               文件之前加上宏定义:                     *
*               # define _USE_LCD_ONLY_WRITE             *
*            5、在调用本库之前,定义RunStringSpeed可   *
*               以设置滚屏的速度。通过在引用前定义       *
*               FlashTimeOut 和 FlashGIFTimeOut 可以   *
*               改变字符闪烁的频率。                     *
*            6、增加一个GIF字幕特效函数。                *
*            7、确定没有LCD复位问题。                  *
*            8、增加对595串行转并行连接的支持。          *
*               需要头文件SerialToCollateral.h         *
***********************************************************/


/********************
* 头 文 件 配 置 区 *
********************/

/********************
*   系 统 宏 定 义*
********************/

/*------------------*
*   常 数 宏 定 义*
*------------------*/


/*------------------*
*   动 作 宏 定 义*
*------------------*/
# define PRINT(a)         LCDDisplayString(a);
# define LOCATE(x,y)      LCDSetXY(x-1,y-1);
# define CLS                LCDWaitForReady();LCDSendCommand(0x01);LCDWaitForReady();LCDSendCommand(0x02);
# define PRINTN(a,b)      LCDDisplayNum((unsigned long)a,b);
# define SHOW_ICON          LCDWaitForReady();LCDSendCommand(0x0f);
# define HIDE_ICON          LCDWaitForReady();LCDSendCommand(0x0c);
# define PRINTD(a,b)      PrintD(a,b);

/********************
*    结构体定义区   *
********************/

/********************
*   函 数 引 用 区*
********************/
extern void LCDInit(void);
extern void LCDSetXY(UINT8 X,UINT8 Y);
extern void LCDDisplayString(UINT8 *String);
extern void LCDDisplayNum(UINT32 Num,UINT8 BitCount);
extern void RunString(UINT8 *String,UINT8 Y,UINT8 StartX,UINT8 EndX);
extern UINT8 StringLength(UINT8 *String);
extern void Flash(UINT8 *String,UINT8 Icon,UINT8 X,UINT8 Y);
extern void FlashStringGroup(UINT8 String[],UINT8 StringCounter,UINT8 X,UINT8 Y);
extern void LCDWaitForReady(void);
extern void LCDSendCommand(UINT8 Command);
extern void LCDSendData(UINT8 Data);
extern void PrintD(INT32 nNumber,UINT8 chCounter);

/********************
*   全局变量引用区*
********************/


#endif

Gorgon_Meducer 发表于 2005-9-12 18:40:36

以下的一些函数主要是输入输出的函数,需要一些宏定义来支持。



/********************************************************

*函数说明:滚屏字幕效果                               *

*输入:    需要滚屏的字符串 长度 位置               *

*说明:    通过修改RunTimeCounter的上限值来修改滚动   *

*            速度。

********************************************************/

void RunString(char *String,char Direction,char Y,char StartX,char EndX)

{

    static char StringHead = 0;

        char SCREEN;

        char a = 0;

        char Point = StringHead;

        char StringLong = StringLenth(String);

        static int RunTimeCounter = 0;

       

        for (a = 0;a<EndX - StartX + 1;a++)

        {

             SCREEN = String;

               Point ++;

               if (Point == StringLong)

               {

                     Point = 0;

               }

        }

       

        for (;a < 17;a++)

        {

          SCREEN =' ';

        }

       

        RunTimeCounter ++;

        if (RunTimeCounter >50)

        {

          StringHead ++;

                RunTimeCounter = 0;

                if (StringHead == StringLong)

          {

                StringHead = 0;

          }

        }

       

        Locate(StartX,Y)

        Print(SCREEN)

}



/********************************************************

*函数说明:字符串长度测试函数                         *

********************************************************/

char StringLenth(char *String)

{

    char n = 0;

        while (*String)

        {

          n++;

                String ++;

        }

       

        return n;

}



/********************************************************

*函数说明:闪烁显示函数                               *

*说明:    这个头文件需要将SystemTimeCounter放到定时*

*            器毫秒中断里面作1 ~ 1000的单项累加。       *

********************************************************/

void Flash(char *String,char Icon,char X,char Y)

{

    char a = 0;

        char StringLong = StringLenth(String);

       

    if (SystemTimeCounter > 499)

        {

          Locate(X,Y)

                Print(String)   

        }

        else

        {

          for (a = X ;a < X+StringLong;a++)

                {

                  Locate(a,Y)

                        Print(&Icon)

                }

        }

}



/********************************************************

*函数说明:用户数据输入函数                           *

*输出:    获取的数值当前的坐标                     *

********************************************************/

unsigned int Input(char x,char y)

{

    char InputBuff = {0x0f,0x0f,0x0f,0x0f,0x0f};

        signed char Tail = 0;

        signed char WritePoint = 0;

        char a = 0;

        char IfInputOk = False;

        unsigned int TempReturn = 0;

       

        while (IfInputOk == False)

        {

          KeyScan();

                AddKeyCode();

          if (GetKeyCode() == True)

                {

                  switch (ReturnKeyNum)

                  {

                  case Key_1:

                          InputBuff = 1;

                                WritePoint ++;

                                if (WritePoint == 4)

                                {

                                  WritePoint = 0;

                                }

                               

                                if (WritePoint > Tail)

                                {

                                  Tail ++;

                                }

                          break;

                        case Key_2:

                          InputBuff = 2;

                                WritePoint ++;

                                if (WritePoint == 4)

                                {

                                  WritePoint = 0;

                                }

                               

                                if (WritePoint > Tail)

                                {

                                  Tail ++;

                                }

                          break;

                        case Key_3:

                          InputBuff = 3;

                                WritePoint ++;

                                if (WritePoint == 4)

                                {

                                  WritePoint = 0;

                                }

                               

                                if (WritePoint > Tail)

                                {

                                  Tail ++;

                                }

                          break;

                        case Key_4:

                          InputBuff = 4;

                                WritePoint ++;

                                if (WritePoint == 4)

                                {

                                  WritePoint = 0;

                                }

                               

                                if (WritePoint > Tail)

                                {

                                  Tail ++;

                                }

                          break;

                        case Key_5:

                          InputBuff = 5;

                                WritePoint ++;

                                if (WritePoint == 4)

                                {

                                  WritePoint = 0;

                                }

                               

                                if (WritePoint > Tail)

                                {

                                  Tail ++;

                                }

                          break;

                        case Key_6:

                          InputBuff = 6;

                                WritePoint ++;

                                if (WritePoint == 4)

                                {

                                  WritePoint = 0;

                                }

                               

                                if (WritePoint > Tail)

                                {

                                  Tail ++;

                                }

                          break;

                        case Key_7:

                          InputBuff = 7;

                                WritePoint ++;

                                if (WritePoint == 4)

                                {

                                  WritePoint = 0;

                                }

                               

                                if (WritePoint > Tail)

                                {

                                  Tail ++;

                                }

                          break;

                        case Key_8:

                          InputBuff = 8;

                                WritePoint ++;

                                if (WritePoint == 4)

                                {

                                  WritePoint = 0;

                                }

                               

                                if (WritePoint > Tail)

                                {

                                  Tail ++;

                                }

                          break;

                        case Key_9:

                          InputBuff = 9;

                                WritePoint ++;

                                if (WritePoint == 4)

                                {

                                  WritePoint = 0;

                                }

                               

                                if (WritePoint > Tail)

                                {

                                  Tail ++;

                                }

                          break;

                        case Key_0:

                          InputBuff = 0;

                                WritePoint ++;

                                if (WritePoint == 4)

                                {

                                  WritePoint = 0;

                                }

                               

                                if (WritePoint > Tail)

                                {

                                  Tail ++;

                                }

                          break;

                               

                        case Key_Delete:

                          if ((WritePoint == 0) && (Tail == 0) && (InputBuff != 0))

                                {

                                  InputBuff = 0x0f;

                                }

                                else if (Tail != 0)

                                {

                                for (a = WritePoint;a<=Tail;a++)

                                        {

                                          InputBuff = InputBuff;

                                        }

                                        InputBuff = 0x0f;

                                        Tail --;

                                       

                                        if (WritePoint > Tail)

                                        {

                                          WritePoint = Tail;   

                                        }

                                }

                          break;

                        case Key_Enter:

                          IfInputOk = True;

                                break;

                  }

               

            switch (ReturnLongKeyPressNum)

                  {

                  case Key_Left:

                          WritePoint --;

                                if (WritePoint < 0)

                                {

                                  WritePoint = Tail;

                                }

                          break;

                        case Key_Right:

                          WritePoint ++;

                                if (WritePoint > Tail)

                                {

                                  WritePoint = 0;

                                }

                          break;

                  }

                }

                Locate(x,y)

               

                for (a = 0;a<4;a ++)

                {

                  if (InputBuff != 0x0f)

                        {

                        PrintN(InputBuff,1)

                        }

                        else

                        {

                          Print(" ")

                        }

                }

                Locate(WritePoint+x,y)

                ShowIcon

        }

   

        HideIcon

        for (a = 0;a<4;a++)

        {

          if (InputBuff != 0x0f)

                {

                TempReturn <<= 4;

                  TempReturn |= InputBuff;

                }

        }       

        return TempReturn;

}





---------------------------------------------------

以下是一些使用以上函数的相关的宏定义。修改后面的数值就可以了。(数值就是键盘扫描码)

# define Key_0            15

# define Key_1            9

# define Key_2            10

# define Key_3            11

# define Key_4            5

# define Key_5            6

# define Key_6            7

# define Key_7            1

# define Key_8            2

# define Key_9            3

# define Key_A            0

# define Key_B            4

# define Key_C            8

# define Key_D            12

# define Key_E            13

# define Key_F            14

# define Key_Left         5

# define Key_Right          7

# define Key_Up             2

# define Key_Down         10

# define Key_Insert         16

# define Key_Enter          19

# define Key_Delete         17

# define Key_Edit         18

# define Key_Reset          7

# define Key_Esc            Key_F      

# define Key_Send         Key_0

Gorgon_Meducer 发表于 2005-9-12 18:49:13

这些头文件的使用示例。



1、初始化

void LCDInit(void);



2、显示字符的定位

   Locate(x,y)——x,y的起点是(1,1)

3、打印字符串

   Print("要显示的内容")或 Print(字符串数组)

4、显示变量

   PrintN(变量名,有效位数)注意显示出来的是十六进制的

5、输入变量(最大4位)

   Result = Input(x,y)    希望在屏幕的什么地方编辑数字

6、滚动字幕

   RunString("字幕内容",1,Y,起始x,终止x)

7、闪烁字幕

   Flash("字幕内容",光标,x,y)         其中,光标是一个char型的数据 如'_'就是用下划线作为光标。



示例1



void main(void)

{

    DeviceInit();

   

        Locate(1,1)

        Print("KeyTest:")

    while(1)

        {

             KeyScan();

               AddKeyCode();

               Locate(2,2)

               PrintN(KeyBuffCounter,2)

               Print(" ")

               PrintN(KeyBuff,2)

               Print(" ")

               PrintN(KeyBuff,2)

        }

       

}

   



示例2

void Welcome(void)

{

    RunString("2005 National Undergradute Electronic Design Contest       Dare To Creat & Enjoy!   ",RunLeft,1,2,15);

    Locate(1,1)

    Print("[")

    Locate(16,1)

    Print("]")

    Flash("Press Any Key...",' ',1,2);

}

Gorgon_Meducer 发表于 2005-9-13 20:28:31

晕,每次放源码就是这样……石沉大海……

看来以后还是不要做一个开源主义者吧……

xiaozhang 发表于 2005-9-13 20:47:31

我来帮你顶!!

Gorgon_Meducer 发表于 2005-9-15 15:29:42

最后顶一次。

IFine 发表于 2005-9-15 15:37:09

顶一下

gongcsf 发表于 2005-9-27 16:38:27

老兄不懂用啊。

gongcsf 发表于 2005-9-27 16:47:55

看到我眼花耳黄,

看后面的例子的话这个应该很好用。比网站的例程好用多了。

不过老兄你能不能解释一下呢。简单点也行啊。

gongcsf 发表于 2005-9-27 16:51:59

如果学通了这个的话我想以后编的东西出来一定有条理多了。

gongcsf 发表于 2005-9-27 23:52:46

这个怎么做成库啊.不会哦.看了半天了.谁教教啊

ztavr 发表于 2005-9-28 16:10:03

我也不懂,感觉很好,能否介绍如何使用?帮你顶

Gorgon_Meducer 发表于 2005-9-28 19:04:58

对不起,我疏忽了,我给大家上传一个使用范例。



点击此处下载armok0174526.rar



[范例说明]

使用M8 外部12M4*5键盘LCD1602 7线连接法(支持读操作)





特别说明,如果是ICC,请务必使用Ctrl + F9编译工程,如果出现端口连接的疑问,以NewIOBoard.h中的硬件宏定义为准。





通讯口:SDA   SCL   INT0    VCC    GND

          PC4   PC5   PD3   VCC    GND



LCD:   DB4——DB7       RS       E   R/W

          PC0——PC3       PC4   PC5    PD3



4*5按键: 1到4列         1到5行

          PB0——PB3   PD7——PD5、PB4、PB5

                  

                  

与显示和按键有关的重要宏定义



/*------------------------------------------------------*

*键盘布局说明                                       *

*                              *

*                        *

*                              *

*                            *

*                            *

*------------------------------------------------------*/

# define Key_0            15

# define Key_1            9

# define Key_2            10

# define Key_3            11

# define Key_4            5

# define Key_5            6

# define Key_6            7

# define Key_7            1

# define Key_8            2

# define Key_9            3

# define Key_A            0

# define Key_B            4

# define Key_C            8

# define Key_D            12

# define Key_E            13

# define Key_F            14

# define Key_Left         5

# define Key_Right          7

# define Key_Up             2

# define Key_Down         10

# define Key_Insert         16

# define Key_Enter          19

# define Key_Delete         17

# define Key_Edit         18

# define Key_Reset          7

# define Key_Esc            Key_F      

# define Key_Send         Key_0

/*---------------------*

*    动 作 宏 定 义    *

*---------------------*/

# define KeyXA               Read_PB0

# define KeyXB               Read_PB1

# define KeyXC               Read_PB2

# define KeyXD               Read_PB3

# define KeyY1               _PD7

# define KeyY2               _PD6

# define KeyY3               _PD5

# define KeyY4               _PB4

# define KeyY5               _PB5

# define SetYHigh            PORTD |= 0b11100000;PORTB |= 0b00110000;



# define LCD_RS            _PC4

# define LCD_RW            _PD3

# define LCD_E               _PC5

# define LCD_BF            Read_PC3

# define LCD_HalfData_Port   PORTC

# define LCD_HalfData_DDR    DDRC



# define LCD_SetWriteData    LCD_HalfData_DDR |= 0x0f;LCD_HalfData_Port &= 0xf0;

# define LCD_SetReadData   LCD_HalfData_DDR &= 0xf0;LCD_HalfData_Port |= 0x0f;

# define LCD_SendHalfCharHigh(a) LCD_HalfData_Port &= 0xf0; LCD_HalfData_Port |= (a>>4);

# define LCD_SendHalfCharLow(a)LCD_HalfData_Port &= 0xf0; LCD_HalfData_Port |= (a<<4>>4);



特别说明,如果是ICC,请务必使用Ctrl + F9编译工程,如果出现端口连接的疑问,以NewIOBoard.h中的硬件宏定义为准。


-----此内容被Gorgon Meducer于2005-09-28,19:58:00编辑过

kinggink888 发表于 2005-9-29 08:07:44

绝对是好贴啊

我近来也是学这个,

真是一份好参考文章

辛苦楼主,

pansa 发表于 2005-9-29 08:48:34

gongcsf 发表于 2005-9-29 12:34:26

刚刚按你的做好了。要把那个通用IO版程序删除才能通过。这个程序我觉得我得看上十天才看得通。

另外在网站买的那块试验版子上的键少了点,



莫:

在的话看看吧。

我感觉按键按下的力需要的太多了。把版子都按弯了。所以以后的版子要不就多搞几个安脚钉的孔,要不就按个轻点的按键,另外的我键生锈了,就是说按钮不是不锈刚的。最好买不锈钢的那种

-----此内容被gongcsf于2005-09-29,12:42:11编辑过


-----此内容被gongcsf于2005-09-29,12:44:18编辑过

Gorgon_Meducer 发表于 2005-9-29 13:33:05

首先,这个实例使用的不是网站的试验板。

其次,由于大量使用头文件,每个头文件的分工十分明确,你可以一个一个的看,不必要系统地看。menu.h是一个关于菜单的头文件,你可以不用去理会它,这个工程我使用ICC创建的,用ICC打开工程文件就可以看到全局。

再次,程序里面大量使用宏定义,所以,你可以从变量的名称和函数的名称领会出他是做什么的。



关于把通用IO版程序删除?我不懂……上传之前,我是编译过的,没有问题,特别强调,我使用的是文件编译的方法而不是工程编译的方法。



可以把出错代码粘贴上来么?一起看一看。

gongcsf 发表于 2005-9-29 13:34:55

我用的是工程编译的。而且我是用的M16的机子。

C:\icc\bin\imakew -f NewIOBoard.mak

    iccavr -c -IC:\icc\include\ -e -DATMEGA -DATMega16-l -g -Mavr_enhancedC:\DOCUME~1\user\桌面\LCD1602演示实例\ChatWithDrawBoard.c

    iccavr -c -IC:\icc\include\ -e -DATMEGA -DATMega16-l -g -Mavr_enhancedC:\DOCUME~1\user\桌面\LCD1602演示实例\test.c

    iccavr -o NewIOBoard -LC:\icc\lib\ -g -ucrtatmega.o -bfunc_lit:0x54.0x4000 -dram_end:0x45f -bdata:0x60.0x45f -dhwstk_size:16 -beeprom:1.512 -fihx_coff -S2 @NewIOBoard.lk   -lcatmega

!E test.o(1197): multiple define: '_main'

!E test.o(1198): multiple define: '_RunString'

!E test.o(1199): multiple define: '_AddKeyCode'

!E test.o(1200): multiple define: '_KeyScan'

!E test.o(1201): multiple define: '_MainMenuInit'

!E test.o(1202): multiple define: '_DelayMs'

!E test.o(1203): multiple define: '_LCDSetXY'

!E test.o(1204): multiple define: '_DelayUs'

!E test.o(1205): multiple define: '_GetKeyCode'

!E test.o(1206): multiple define: '_Timer0Init'

!E test.o(1207): multiple define: '_Welcome'

!E test.o(1208): multiple define: '_LCDSendData'

!E test.o(1209): multiple define: '_LCDDisplayNum'

!E test.o(1210): multiple define: '_SetCircleCenter'

!E test.o(1211): multiple define: '_DeviceInit'

!E test.o(1212): multiple define: '_WriteEEP'

!E test.o(1213): multiple define: '_Flash'

!E test.o(1214): multiple define: '_Delay'

!E test.o(1215): multiple define: '_SendPointData'

!E test.o(1216): multiple define: '_Input'

!E test.o(1217): multiple define: '_MenuMain'

!E test.o(1218): multiple define: '_LCDSendCommand'

!E test.o(1219): multiple define: '_LCDDisplayString'

!E test.o(1220): multiple define: '_ShowMenu'

!E test.o(1221): multiple define: '_NullSubs'

!E test.o(1222): multiple define: '_PortInit'

!E test.o(1223): multiple define: '_NowKeyPressCheck'

!E test.o(1224): multiple define: '_SendCircleData'

!E test.o(1225): multiple define: '_LoadEEP'

!E test.o(1226): multiple define: '_Uart0Init'

!E test.o(1227): multiple define: '_LCDInit'

!E test.o(1228): multiple define: '_StringLenth'

!E test.o(1229): multiple define: '_MenuInitialation'

!E test.o(1230): multiple define: '_CircleMenuInit'

!E test.o(1231): multiple define: '_CheckBusy'

!E test.o(1232): multiple define: '_Uart0_Rx_Isr'

!E test.o(1233): multiple define: '_LCDWaitForReady'

!E test.o(1234): multiple define: '_Uart0_Tx_Isr'

!E test.o(1235): multiple define: '_Timer0OvfIsr'

!E test.o(1236): multiple define: '_PointEdit'

!E test.o(1237): multiple define: '_PORTDefine'

!E test.o(1266): multiple define: '_KeyPressTimeCounter'

!E test.o(1267): multiple define: '_NowTail'

!E test.o(1268): multiple define: '_ReturnKeyNum'

!E test.o(1269): multiple define: '_DisplayPoint'

!E test.o(1270): multiple define: '_DisplayStart'

!E test.o(1271): multiple define: '_SystemTimeCounter'

!E test.o(1272): multiple define: '_LongKeyPressNum'

!E test.o(1273): multiple define: '_UserChoose'

!E test.o(1274): multiple define: '_WelComeTimeCounter'

!E test.o(1275): multiple define: '_KeyBuffHeadPoint'

!E test.o(1276): multiple define: '_KeyBuffTailPoint'

!E test.o(1277): multiple define: '_KeyNum'

!E test.o(1278): multiple define: '_DelayTimeCounter'

!E test.o(1279): multiple define: '_ReturnLongKeyPressNum'

!E test.o(1280): multiple define: '_KeyBuffCounter'

!E test.o(1281): multiple define: '_MenuPoint'

!E test.o(1286): multiple define: '_CHR'

!E test.o(1294): multiple define: '_RX'

!E test.o(1295): multiple define: '_RY'

!E test.o(1296): multiple define: '_PointCount'

!E test.o(1297): multiple define: '_R'

!E test.o(1298): multiple define: '_PointBuff'

!E test.o(1313): multiple define: '_KeyBuff'

!E test.o(1314): multiple define: '_PORTA_BIT'

!E test.o(1315): multiple define: '_PORTB_BIT'

!E test.o(1316): multiple define: '_PORTC_BIT'

!E test.o(1317): multiple define: '_PORTD_BIT'

!E test.o(1318): multiple define: '_CircleMenu'

!E test.o(1319): multiple define: '_MainMenu'

!E test.o(1320): multiple define: '_MaxItems'

!E test.o(1321): multiple define: '_MenuNull'

C:\icc\bin\imakew.exe: Error code 1

Done: there are error(s). Exit code: 1



现在正在用 AVR Studio 4 一句句的看呢。等一下上个图上来。

我删了TEST。C之后就可以了。

现在运行之后就在第一行显示流动的2005 National Undergradute Electronic Design Contest       Dare To Creat & Enjoy!

第二行是一个FLASH的press any key....

应该是可以正常用了。





-----此内容被gongcsf于2005-09-29,13:37:37编辑过


-----此内容被gongcsf于2005-09-29,13:43:03编辑过

Gorgon_Meducer 发表于 2005-9-29 13:45:05

你要使用Ctrl+F9编译test.c

不要直接编译

gongcsf 发表于 2005-9-29 13:55:34

哦。我知道了。TEST。C是一个独立的模块吧。只是单独用来试验LCD的对吧。

gongcsf 发表于 2005-9-29 13:57:43

就是说以后要用到1602B的这些功能的话在头文件里加入ExtendNewIOBoard.h就可以了吧。

当然还有一些别的麻烦事但是总休来说就是这样子吧。

等我看清楚之后自己把这个LCD的文件分离出来吧。

Gorgon_Meducer 发表于 2005-9-29 17:51:20

test.c的确是我测试RD_LCD1602B.h的一个模块。

如果你想通过简单包含ExtendNewIOBoard.h来实现对1602的支持也是可以的。但是说明,第一,占用大量系统资源,因为不是最小系统,第二,根据不同的硬件系统会有所差异。



特别说明一下我的编程习惯:

1、写一个头文件来驱动底层的硬件,包括初始化等等,最后实现一个硬件API库提供给上层。

2、写一个算法驱动库来调用硬件API库函数,给最上层的工程提供必要的类似伪代码的方法和函数,便于在实现算法上使程序简洁明了,修改简单。

3、最上层抛开一切硬件底层的概念,利用算法描述您想实现的所有功能。



这样的好处是,通过1和2来作铺垫可以使最宝贵的算法完全抛开硬件,做到类似Java的一次编程,终生受用的特点,尤其适用于机器人的程序编写。当然,1 2的就是我们自己编写的虚拟机。

当然,完全实现算法和底层不相关还需要养成一套宏定义的命名习惯和规则,摸索一些增强代码通用性的经验。



说了这么多,只是希望大家能够看懂我的代码——说实话,说要花费十天才能看懂我的代码,我觉得很委屈,我在代码的异读性上花费了很多心血哈……呵呵。





--------------------------------------



驱动LCD1602需要的结构是

首先编写一个描述你硬件连接的底层驱动库,需要包括驱动LCD1602的一些基本宏定义(在12楼和RD_LCD1602B.h说明中已经说清楚了),还要包括基本的Us延时和Ms延时函数。在这个底层驱动库里面记得在一开始引用RD_ATMage16L.h(如果你是M16的话),这样就支持了位操作。



其次,在RD_LCD1602B.h的开始处加上对你刚才写的那个底层驱动库的引用。



最后,把RD_LCD1602B.h引用到你的工程中就完成了整个库的调用工作,并且支持Print、PrintN、Locate、CLS、ShowIcon、HideIcon等基本语句。



要想使用1楼的那些特效函数,只需要把那些函数粘贴到你的主程序里面就可以了,当然,记得要看使用说明,补充适当的宏定义和函数哦。
-----此内容被Gorgon Meducer于2005-09-29,18:01:05编辑过

gongcsf 发表于 2005-9-29 17:59:12

谢谢。先下班回家慢慢看。

kinggink888 发表于 2005-9-29 21:35:37

这个好东西啊,

谢问下我现在用的是4X4键盘,做个LCD显示键入数字

可是4X4键盘不显作用,详细见

http://www.ouravr.com/bbs/bbs_content.jsp?bbs_sn=431809&bbs_page_no=1&bbs_id=1008

能帮忙看下是什么问题,

还有你的程序如果有图结合就更好理解了,可以上转图吗

Gorgon_Meducer 发表于 2005-9-29 22:04:51

我使用的是4*5的键盘,是全国电子设计的时候赶制出来的,现在没有实物了。抱歉,无法提供图片资料。不过从当时保留的技术资料还是可以看出很多东西的。



/*------------------------------------------------------*

*键盘布局说明                                       *

*                              *

*                        *

*                              *

*                            *

*                            *

*------------------------------------------------------*/

这个是键盘布局。



具体不明白的可以大家一起讨论哈。

gongcsf 发表于 2005-9-29 23:43:11

"说了这么多,只是希望大家能够看懂我的代码——说实话,说要花费十天才能看懂我的代码,我觉得很委屈,我在代码的异读性上花费了很多心血哈……呵呵。 "





哈哈.这个不是你的问题.是我的问题.我是初学者,也只是明白一点点编程而以.

现在正在学习别人的编程方法和习惯,说实话看懂某个程序之后心里面实在是小有

点点高兴和收获,总有一天我也会有自己的编程思路和习惯的了. 你的好像是给1602B做了一个驱动程序一样.很有意思,方便多了.



我也不知道怎么说好.感觉如果是上下文结构或者是平行结构的话就容易读很多.

我是觉得程序里交叉得比较多所以看多句就要理清头脑一下了.



另外你有没什么联系方法没有啊.做为一个初学者有些问题是一下子想不通的,所

以想不时的打扰一下你行吗.

我QQ:79144229

MSN:gongcsf@hotmail.com

mail:mailroot@cleanera.net



msn比较少用.






-----此内容被gongcsf于2005-09-29,23:49:31编辑过

wangbanhuang 发表于 2006-1-4 09:09:04

不好意思,看不懂

我现要想用3X4键盘控制LCD显示,键盘分别表示:0-9、*、/



我用的编译器是CVAVR,M16,LCD:1602

找资料好几天了,没什么头绪,谁能给换指点一下,谢谢



下面这是我东拼西凑搞出来的程序,估计是没用的,还请大家给看一下:



#include <mega16.h>

#asm

   .equ __lcd_port=0x15 ;PORTC

#endasm

#include <lcd.h>

#include <delay.h>

int lcd_buff;

char key_stime_counter;

bit key_stime_ok;

// Timer 0 比较匹配中断服务,2ms定时

interrupt void timer0_comp_isr(void)

{   

    lcd_puts(lcd_buff);

    if (++key_stime_counter >=5)   

    {   

      key_stime_counter = 0;   

      key_stime_ok = 1;    // 10ms到

    }

}

//=================================

#define No_key255

#define K1_1 1

#define K1_2 2

#define K1_3 3

#define K2_1 4

#define K2_2 5

#define K2_3 6

#define K3_1 7

#define K3_2 8

#define K3_3 9

#define K4_1 10

#define K4_2 0

#define K4_3 11

#define Key_mask0b00000111



char read_keyboard()

{

    static char key_state = 0, key_value, key_line;

    char key_return = No_key,i;

    switch (key_state)

    {

    case 0:

      key_line = 0b00001000;

      for (i=1; i<=4; i++)                // 扫描键盘

      {

            PORTD = ~key_line;            // 输出行线电平

            PORTD = ~key_line;            // 必须送2次!!!

            key_value = Key_mask & PIND;    // 读列电平

            if (key_value == Key_mask)

                key_line <<= 1;             // 没有按键,继续扫描

            else

            {

               key_state++;               // 有按键,停止扫描

               break;                     // 转消抖确认状态

            }

      }

      break;

    case 1:

      if (key_value == (Key_mask & PIND))// 再次读列电平,

      {

            switch (key_line | key_value)   // 与状态0的相同,确认按键

            {                               // 键盘编码,返回编码值

             case 0b00001110:      

                key_return = K1_1;      

                break;      

             case 0b00001101:      

                key_return = K1_2;      

                break;      

             case 0b00001011:      

                key_return = K1_3;

                break;

             case 0b00010110:      

                key_return = K2_1;      

                break;      

             case 0b00010101:      

                key_return = K2_2;      

                break;      

             case 0b00010011:      

                key_return = K2_3;      

                break;      

             case 0b00100110:      

                key_return = K3_1;      

                break;      

             case 0b00100101:      

                key_return = K3_2;      

                break;      

             case 0b00100011:      

                key_return = K3_3;      

                break;

             case 0b01000110:      

                key_return = K4_1;      

                break;      

             case 0b01000101:      

                key_return = K4_2;      

                break;      

             case 0b01000011:      

                key_return = K4_3;      

                break;

            }

            key_state++;   // 转入等待按键释放状态

      }

      else

            key_state--;       // 转入等待按键释放状态

      break;

    case 2:                   // 等待按键释放状态

      PORTD = 0b00000111;   // 行线全部输出低电平

      PORTD = 0b00000111;   // 重复送一次

      if ( (Key_mask & PIND) == Key_mask)

            key_state=0;   // 列线全部为高电平返回状态0

      break;   

    }

    return key_return;

}

//===========================================   

void main(void)

{

    char i,key_temp;

    PORTD=0xFF;

    DDRD=0xF8;

    lcd_init(16);

    TIMSK=0x02;

    for (i=0; i<16 ;i++)

    {lcd_buff= 1;}

    #asm("sei")

    while (1)

    {

      key_stime_ok = 0;    // 10ms到   

      key_temp = read_keyboard();// 调用键盘接口函数读键盘   

      if (key_temp != No_key)   

      {       // 有按键按下      

      for (i=0; i<16; i++)      

      {lcd_buff = lcd_buff;}// LED显示左移一位      

      lcd_buff = key_temp;   // 最右显示新按下键的键值

      }

      lcd_clear();

      lcd_puts(lcd_buff);

    };

}

sky134579 发表于 2006-3-29 20:06:29

顶,狂顶!

初学者的宝藏啊!

zuoxg88 发表于 2006-3-29 21:10:49

好贴,我顶,

jackrich 发表于 2006-3-30 08:09:33

谢谢

99stone 发表于 2006-10-19 14:43:50

好东西

99stone 发表于 2006-10-19 15:56:55

C:\icc\bin\iccavr-Ic:\icc\include\ -e -DATMega8-l -g -Mavr_enhanced_small -Wa-W-LC:\icc\lib -Wl-W -bfunc_lit:0x26.0x2000 -dram_end:0x45f -bdata:0x60.0x45f -dhwstk_size:16 -beeprom:1.512 -fihx_coff -S2 test.c

Device 88% full.

Cannot find source file C:\Documents

Cannot find source file C:\test.c

Done.



Ctrl + F9编译工程 出现上面东西没用过ICC 不知道什么意思

99stone 发表于 2006-10-19 15:58:55

编译有文件生成 烧入1602显示 pvyitr

rivergd 发表于 2007-2-9 20:53:51

狂顶

luoyiming1984 发表于 2007-3-25 10:14:51

天书啊,LZ不愧是软件高手,可是我们不会用。



请楼主放个include的main程序,主要是端口配置的

wj414 发表于 2007-3-30 23:00:26

能不能加点注释呀!

有点茫然!

zsxkaiser 发表于 2007-4-9 21:38:58

谢谢楼主!

gcc4isr 发表于 2007-5-16 00:18:00

thanks.

Forever 发表于 2007-11-7 13:29:07

看了,不错,顶!

SingleCPU 发表于 2007-11-7 18:36:54

好长啊,不如直接用个四线或8线的程序就行了。也可以根据硬件设置而变化。
用头文件觉得没什么必要,本来1602就是个不复杂的东西

iamcyf 发表于 2007-11-24 20:50:08

顶,真是一个慷慨的好人啊。
不顶哪行。

Chenxg 发表于 2008-1-20 09:20:20

我顶,我再顶.

admvip 发表于 2008-1-21 11:12:15

这几天一直在研究这个1602头文件,终于看明白了一些,虽然程序多,比较复杂,但是发现可移植性非常好,不愧是通用1602头文件。谢谢楼主放开源代码!

hl0716 发表于 2008-1-21 11:32:15

哈哈,我也看看

Chenxg 发表于 2008-3-15 13:11:42

谢谢了.

34480016 发表于 2008-3-15 14:13:54

分享一个 1602lcd总线方式.pdf
点击此处打开ourdev_231195.pdf(文件大小:442K)

lxx_sea_sky 发表于 2008-6-13 09:47:10

长长的,晕晕的,虽然知道傻大大的库应该没问题,但自己没看透彻,不放心用啊。
可能是用熟的原因,傻大大注释很少(很多人都这样,包括我),但造成阅读困难啊,呵呵

Gorgon_Meducer 发表于 2008-6-13 09:55:14

to 【48楼】 lxx_sea_sky
    原来的函数库太古老了……被证实有问题……公布一个新的(已经更新到楼主位)
    点击此处下载 ourdev_309242.rar(文件大小:5K) (原文件名:LCD1602.rar)

eagle_avr 发表于 2008-6-26 15:32:21

支持!

lijiji1204 发表于 2008-6-27 19:31:12

厉害,向傻孩子学习....

lijiji1204 发表于 2008-6-27 19:34:01

我是名大二的学生,想参加明年的国赛,单片机没什么基础,不知道傻孩子花了多长时间把AVR玩熟的,还有就是有没什么好点的资料,初学者适用的那种,推荐一下,谢谢...

Gorgon_Meducer 发表于 2008-6-27 21:30:57

to 【52楼】 lijiji1204
    我从大一入学后2个月开始接触单片机,到了第二年5月份已经可以处理大部分资源了。到了9月份参加了电子设计大赛,能够较为熟练的编写程序。其中没有诀窍,就是每天平均100行代码……

dogcome 发表于 2008-6-28 00:21:38

mark

lijiji1204 发表于 2008-6-28 21:33:39

昨天在淘宝上定了你的书,是我一个朋友推荐的,说很适合入门级的单片机爱好者学习,很期盼哦~~~~今天再写个小程序的时候碰到个小问题,使用定时器0开中断我写了TVCCR0=0x06,TCNT0=06;好像不能进入中断,我知道肯定少了两条语句,只是不知道怎么写,希望你能帮帮我,谢谢。。。

Gorgon_Meducer 发表于 2008-7-18 01:40:04

to 【55楼】 lijiji1204
    慢慢看书,你就知道了。其实,你可以试一试ICC的代码生成器,很方便哈。

shupeng_avr 发表于 2008-8-2 17:29:36

我怎么觉得把一个1602这么简单的东西搞的这么复杂啊?!!

我用51点起来,也不用200行代码啊!

xupeixu 发表于 2008-9-9 09:26:20

现在不是点亮的问题了,是怎么把这东西点好的问题!

yxlcarter 发表于 2008-9-11 14:53:23

唉,都是高手啊,惭愧啊。

Gorgon_Meducer 发表于 2008-11-27 08:00:24

to&nbsp;【62楼】&nbsp;flying_study&nbsp;小蒋

&nbsp;&nbsp;&nbsp;&nbsp;我没有遇到过这种情况。你试试不停的在同一个位置显示同一个字符串,看看是否有这个问题。

如果有,你尝试更新一下函数库。

&nbsp;&nbsp;&nbsp;&nbsp;点击此处下载&nbsp;ourdev_516415.rar(文件大小:5K)&nbsp;(原文件名:LCD1602.rar)&nbsp;

antonine 发表于 2008-11-29 01:07:56

mark

frank21 发表于 2008-12-3 13:40:33

不知道是不是我没有搞对,我发现傻孩子在12楼公布的例程中的头文件和楼主位的程序不一样。



另外,傻孩子在公布的两段程序,RD_LCD1602b.h和RD_LCD1602b.c间是什么关系,有了.h文件了为什么还要.c文件?

小弟菜鸟请各位指点!

Gorgon_Meducer 发表于 2008-12-3 18:29:10

to&nbsp;【65楼】&nbsp;frank21&nbsp;&nbsp;

&nbsp;&nbsp;&nbsp;&nbsp;12楼的程序是老版本的,楼主位的程序是最新版本的,二者确实有很大区别。

另外关于.c和.h的区别,网上有很多资料,这里我简单说明一下:

&nbsp;&nbsp;&nbsp;&nbsp;.c文件存放函数和变量的实体,编译的时候会生成一个.o文件

&nbsp;&nbsp;&nbsp;&nbsp;.h文件存放必要的接口函数的外部引用以及必要的变量引用,都是用extern

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;关键字来修饰。.h中不能存放函数的实体。我在老版本头文件中犯过这个

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;错误,现在希望你不要犯同样的错误。

ddaitt999 发表于 2008-12-4 10:58:42

好贴顶起来~~~!!

frank21 发表于 2008-12-4 14:57:05

【66楼】&nbsp;Gorgon&nbsp;Meducer&nbsp;傻孩子&nbsp;



我开了一个帖子http://ouravr.com/bbs/bbs_content.jsp?bbs_sn=1912535&bbs_id=9999&nbsp;&nbsp;请大家介绍下各自的编程习惯共初学者学习。

请你过来介绍下经验阿&nbsp;&nbsp;^_^

eduhf_123 发表于 2008-12-11 21:39:45

呵呵,我来在鸡蛋里挑点骨头:

用define定义的宏,不需要在宏体末尾加上分号。

eduhf_123 发表于 2008-12-11 21:44:22

即使宏体包括多条C语句,也只需要在各C语句之间插入分号,最后一条语句后面不需要。

而且这种情况通常建议使用大括号“{}”及续行指示符“\”,最后的大括号的后面也是不需要分号的。

ligongchen 发表于 2008-12-12 16:52:58

mark&nbsp;and&nbsp;thank&nbsp;you

YANGFAN 发表于 2008-12-12 20:45:25

看这样的程序很舒服,想艺术品一样!

wisebaby 发表于 2009-3-12 19:11:13

不知道有多少人下载了这个东西了.的确写的不错.

Gorgon_Meducer 发表于 2009-3-12 20:34:41

to 【67楼】 eduhf_123 经历
    这个问题此前有人和我提出过,我考虑再三保留这个分号。因为我的宏使用的时候
不是按照函数混用的……一般用大小区别,不加分号以示其为宏……
    这属于个性风格,不是我推荐的风格,我推荐的风格是:

# define SAFE_CODE_PERFORMANCE(__CODE)    \
             do\
             {\
               unsigned char chSREG = SREG;\
               if (chSREG & (1 << 7))\
               {\
                     __asm__ __volatile__ asm("cli");\
                     __CODE;\
                     __asm__ __volatile__ asm("sei");\
               }\
               else\
               {\
                     __CODE;\
               }\
             }\
             while (0)

wisebaby 发表于 2009-3-13 13:07:31

void RunString(char *String,char Direction,char Y,char StartX,char EndX)

char Direction 这个参数很雷人啊... 呵呵.

feiyang007 发表于 2009-3-24 00:43:43

好呀,今天终于发现的!!敬礼!!

Gorgon_Meducer 发表于 2009-3-24 00:54:32

to 【72楼】 wisebaby 明君
    原本想实现这个功能,但是后来没有做……不过把接口留下了……

weimenlove 发表于 2009-5-19 16:57:22

Mark

seckuola 发表于 2009-5-23 15:55:16

mark

shangzhenwei 发表于 2009-6-8 17:23:19

貌似很难!正在学习。

shangzhenwei 发表于 2009-6-9 14:46:00

傻孩子,

# define SetReadState       LCD_SET_READ_DATA;LCD_RS = LCD_COMMAND;LCD_RW = LCD_READ;

这句中的LCD_SET_READ_DATA;是什么意思啊,在前面没有定义时,可以直接写在这里吗?

Gorgon_Meducer 发表于 2009-6-9 15:24:00

*[使用说明]                                              *
*            1、需要底层硬件驱动函数支持               *
*               基本的宏定义:                           *
*               LCD_RS   LCD_RW   LCD_E                  *
*               LCD_SET_WRITE_DATALCD_SET_READ_DATA    *
*               LCD_SEND_HALF_CHAR_HIGH(a)               *
*               LCD_SEND_HALF_CHAR_LOW(a)                *
*               当处于串行状态下时,只定义LCD_RS         *
*               LCD_E LCD_SEND_HALF_CHAR_HIGH(a)         *
*               LCD_SEND_HALF_CHAR_LOW(a)                *

0620221 发表于 2009-6-18 08:27:41

dddddddddddddddd

tiger1125 发表于 2009-8-6 00:46:18

厉害啊

hm_huang 发表于 2009-8-7 22:47:44

谢谢分享!

chengyuwang 发表于 2009-9-20 11:07:40

楼主,你好我想和你聊聊,加我QQ183163631!
谢谢

xsemir 发表于 2010-8-10 09:02:10

回复【86楼】chengyuwang
-----------------------------------------------------------------------

楼主做你徒弟 加我Q:我是初学者.希望同意、、、

KevinLee 发表于 2010-11-2 18:47:48

学习啊。

jy877863 发表于 2010-11-17 23:34:24

绝对是好贴啊 我近来也是学这个, 真是一份好参考文章 辛苦楼主

guxingganyue 发表于 2010-11-19 10:20:39

我顶

wnstony 发表于 2011-1-20 19:08:28

416446891 发表于 2011-1-20 20:13:58

MARK

summerstar 发表于 2011-5-4 22:23:50

mark

bms513 发表于 2020-7-3 17:02:06

上手1602,mark一下
页: [1]
查看完整版本: [分享][2008-6-13 update]一些关于1602显示的头文件