angmall 发表于 2023-2-10 00:04:17

使用2位数据线做控制 LCD1602用HC164

本帖最后由 angmall 于 2023-2-10 00:04 编辑

I/O口 不够,咋办 使用2位数据线做控制 LCD1602用 HC164 的串行输入控制 扩展输出 8位



/* Main.c file generated by New Project wizard
*
* Created:   周四 2月 9 2023
* Processor: STC15W4K32S4
* Compiler:Keil for 8051
I/O口 不够,咋办 使用2位数据线做控制 LCD1602用 HC164 的串行输入控制 扩展输出 8位
*/

#include <reg51.h>
#include <stdio.h>
#include <intrins.h >//头文件的包含 _nop_()

//#define MAIN_Fosc       11059200UL//定义主时钟
#define MAIN_Fosc       12000000UL//定义主时钟

sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;

typedef unsigned char      uint8;          // 无符号8位整型变量 //
typedef unsigned int       uint16;          // 无符号16位整型变量 //

/********************************************************************************************
// 指令集 //将所有可能用到的指令先预定义一下,方面以后的使用
/********************************************************************************************/
#define CMD_clear       0x01             // 清除屏幕
#define CMD_back       0x02             // DDRAM回零位
#define CMD_dec1       0x04             // 读入后AC(指针)减1,向左写
#define CMD_add1      0x06             // 读入后AC(指针)加1,向右写
#define CMD_dis_gb10x0f             // 开显示_开光标_开光标闪烁
#define CMD_dis_gb20x0e             // 开显示_开光标_关光标闪烁
#define CMD_dis_gb30x0c             // 开显示_关光标_关光标闪烁
#define CMD_OFF_dis0x08             // 关显示_关光标_关光标闪烁
#define CMD_set82   0x38             // 8位总线_2行显示
#define CMD_set81   0x30             // 8位总线_1行显示(上边行)
#define CMD_set42   0x28             // 4位总线_2行显示
#define CMD_set41   0x20             // 4位总线_1行显示(上边行)
#define lin_1         0x80             // 4位总线_1行显示(上边行)
#define lin_2         0xc0             // 4位总线_1行显示(上边行)

sbit   LCD1602_RS=P2^1;/* Data Command Pin1 data0 command pin 4*/
sbit   LCD1602_E =P2^0;/* LCD Enable Signalpin 6*/
bit    rs = 0;             // lcd 'rs' flag

void _delay_us(uint16 i)
{
      while(i--)
   {      
      _nop_();
      _nop_();
      _nop_();
      _nop_();
   }
}

void Delay1ms(unsigned int xms)
{
      uint16 x,y;
      for(x=xms;x>12;x--)
            for(y=169;y>0;y--);
}

/********************************************************************************************
// 写数据程序 //
/********************************************************************************************/
void LCD1602_Write(uint8 LCD1602_work) {
    uint8 bitctr = 8;

   do                         // start of bit clock cycle
   { if(!(LCD1602_work & 128))      // if b7 is a '0' bit
         LCD1602_RS = 0;       // start clock cycle for a '0'
       _delay_us(55);            // charge or drain cap to 3t
      
               LCD1602_RS = 0;         // start clock cycle for a '1'
               LCD1602_RS = 1;         // clock out the '0' or '1'

       LCD1602_work <<= 1;      // prep for next bit
   } while(--bitctr);         // until all 8 bits clocked out

   if(!rs) LCD1602_RS = 0;   // make clk pin = rs flag
   LCD1602_E = 1;         // latch 595, pulse LCD 'E' pin
   LCD1602_E = 0;            //"
   LCD1602_RS = 1;            // always leave clk pin high


}

/********************************************************************************************
// 写指令程序 //
/********************************************************************************************/
void LCD1602_WriteCMD(uint8 LCD1602_command) {
rs = 0;LCD1602_Write(LCD1602_command); rs = 1;
}
/********************************************************************************************
// 初始化
/********************************************************************************************/
void LCD1602_Init(void){

    LCD1602_E = 0;
    LCD1602_RS = 1;
    Delay1ms(100);
      LCD1602_WriteCMD(CMD_set82);//16*2显示,5*7点阵,8位数据
      LCD1602_WriteCMD(CMD_set82);
      LCD1602_WriteCMD(CMD_clear);
      LCD1602_WriteCMD(CMD_back);
      LCD1602_WriteCMD(CMD_add1);
      LCD1602_WriteCMD(CMD_dis_gb3);
    Delay1ms(2);

}
/********************************************************************************************
// 打印字符串程序 // (本函数调用指针函数)
// 第一行位置 0x00~0x0f第二行位置 0x40~0x4f
/********************************************************************************************/
void print_str(uint8 a, uint8 *str){
      LCD1602_WriteCMD(a | 0x80);
      while(*str != '\0'){
                LCD1602_Write(*str++);
      //_delay_us(2);
      }
      *str = 0;
}
/********************************************************************************************
// 打印单字符程序 //
/********************************************************************************************/
/*
void print_char(uint8 a,uint8 t){
      LCD1602_WriteCMD(a | 0x80);
      LCD1602_Write(t);
}*/

void main(void)
{

    P2M0 = 0x00;
    P2M1 = 0x00;


    LCD1602_Init();
      print_str(0x80,"Histcaimcu.com");
    Delay1ms(1);
         print_str(0xC0,"0123456789ABCDEF");

// Write your code here
   while (1){
         //print_str(0xC0,"0123456789ABCDEF");
    }
      
}









angmall 发表于 2023-2-11 22:36:27

STC8H8K64U转STC89-打狗棒使用2位数据线做控制 LCD1602用 HC164 的串行输入控制 扩展输出 8位


神农鼎 发表于 2023-2-11 22:51:50

I/O 不够,可以 用 开天斧-STC8H8K64U-45MHz-LQFP64转DIP64

https://nwzimg.wezhan.cn/contents/sitefiles2057/10287325/images/37640751.jpg


深圳国芯人工智能有限公司-核心功能实验板 (stcai.com)

angmall 发表于 2023-6-5 08:05:20

神农鼎 发表于 2023-2-11 22:51
I/O 不够,可以 用 开天斧-STC8H8K64U-45MHz-LQFP64转DIP64




不是每个项目都可以用这么多 I/O 的单片机。
这里给的是,怎么用最少的I/O脚来控制LCD1602液晶显示。

神农鼎 发表于 2023-6-5 11:26:36

应该有 SPI-LCD12864,SPI-LCD1602
应该有 I2C-LCD12864,I2C-LCD1602


















梁工 发表于 2023-6-5 15:10:06

使用I2C接口的OLED或LCD1602,2线即可。74HC164输出时,每一个输出都会“闪烁”一下,一般建议使用有锁存功能的74HC595来扩展IO输出,3线即可,可以多片级联。
页: [1]
查看完整版本: 使用2位数据线做控制 LCD1602用HC164