单片机学习小组
直播中

李颜

7年用户 1409经验值
私信 关注

STM32如何实现LCD12864显示?

STM32如何实现LCD12864显示?

回帖(1)

荣春梅

2022-2-16 10:17:28
工作于并行模式时的引脚定义:
PIN1------------------GND   电源接入-,一般接0V(视具体液晶型号)
PIN2------------------电源接入+,一般接5V(视具体液晶型号)
PIN3------------------对比度调整端,VDD和GND接可调电阻两端,中间抽头接至V0
PIN4------------------RS指令/数据选择
PIN5------------------R/W读写选择
PIN6------------------E,使能信号
PIN7------------------D0,数据位0
PIN8------------------D1,数据位1
PIN9------------------D2,数据位2
PIN10------------------D3,数据位3
PIN11------------------D4,数据位4
PIN12------------------D5,数据位5
PIN13------------------D6,数据位6
PIN14------------------D7,数据位7
PIN15------------------PSB  并行:PSB=1,可以接VCC,串行:PSB=0,一般接GND
PIN16------------------NC,不连接
PIN17------------------~RST,模块复位,可不连接
PIN18------------------NC,不连接
PIN19------------------LED+,背光+,一般接5V(视具体液晶型号)
PIN20------------------LED-,背光-,一般接GND
工作于串行模式时的引脚定义:
PIN1------------------GND   电源接入-,一般接0V(视具体液晶型号)
PIN2------------------电源接入+,一般接5V(视具体液晶型号)
PIN3------------------对比度调整端,VDD和GND接可调电阻两端,中间抽头接至V0
PIN4------------------RS(CS),片选
PIN5------------------R/W(SID),数据
PIN6------------------E(SCK),脉冲
PIN7------------------NC,不连接
PIN8------------------NC,不连接
PIN9------------------NC,不连接
PIN10------------------NC,不连接
PIN11------------------NC,不连接
PIN12------------------NC,不连接
PIN13------------------NC,不连接
PIN14------------------NC,不连接
PIN15------------------PSB  并行:PSB=1,可以接VCC,串行:PSB=0,一般接GND
PIN16------------------NC,不连接
PIN17------------------~RST,模块复位,可不连接
PIN18------------------NC,不连接
PIN19------------------LED+,背光+,一般接5V(视具体液晶型号)
PIN20------------------LED-,背光-,一般接GND
12864液晶并口驱动程序用的比较多,但是考虑到有的时候单片机或者MCU的IO口有限时就可以使用串行驱动方法。以下是12864液晶串行时序图,下面就根据这个图来分析一下12864串行时序的实现,只有真正弄清楚了时序图才能真正了解串行传输的原理。

从图上可以看出串行传输时需要用到CS,SCLK,SID三根信号线,但是由于CS是高电平有效,所以也可以把CS长接高电平,那样就只需要两根线就OK了,当然当使用12864串行模式时,PSB引脚必须接低电平,复位RST引脚可以悬空不接,因为12864内部有上电复位威廉希尔官方网站 。
由于数据是传输是以一个字节8bits为单位,所以下面贴出传输一个字节的函数实现
从时序图上可以看出,要想完整的把一个字节的数据传出去,需要传送三次才能实现,也就是需要传送三个字节,这三个字节分别是:命令控制字,字节的高四位+低四位0组成的字节,字节的低四位+高四位0组成的字节。
                                                                   命令控制字11111RWRS0
RW代表读还是写液晶,为0代表写,为1代表读。RS代表写命令还是数据,为0代表写命令,为1代表写数据,其余6位固定。所以假设要向液晶写数据,就必须首先发送11111010,写命令就发送11111000。
下面是程序的具体实现,这是关键!
硬件:
单片机型号:STM32L052K8*     其实不管哪款单片机实现效果是一样的
液晶型号:LCD12864
接线:
PA0  接   RS(CS)
PA1  接   R/W(SID)
PA2  接   E(SCK)
PA3  接   RST    这个可以不接,悬空或接高电平(VCC),液晶内部有上电复位的功能,看自己的实现需要添加

lcd12864.c


#include "lcd12864.h"
#include "main.h"
/******************************************
*名称:void Write_8bits(uint8_t W_bits)
*功能:按照液晶的串口通信协议,发送数据
*输入:W_bits
*输出:无
*******************************************/

void Write_8bits(uint8_t W_bits)
{
        uint8_t i,Temp_data;
        for(i=0; i<8; i++)//总共移动八次,就可以把8bits数据全部传完
        {
                Temp_data = W_bits;
                Temp_data <<= i;//把数据依次左移
                if((Temp_data&0x80)==0)  //判断对应位是否为0
                {
                        HAL_GPIO_WritePin(SID_GPIO_Port,SID_Pin,GPIO_PIN_RESET);
                        HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_RESET);        //SCLK = 0;//在时钟的下降沿把数据传输出去
                        HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_SET);                // SCLK = 1;//置高电平,为下次传输做准备
                }
                else         //对应位为1
                {
                        HAL_GPIO_WritePin(SID_GPIO_Port,SID_Pin,GPIO_PIN_SET);                //SID = 1;
                        HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_RESET);        //SCLK = 0;//在时钟的下降沿把数据传输出去
                        HAL_GPIO_WritePin(CLK_GPIO_Port,CLK_Pin,GPIO_PIN_SET);                // SCLK = 1;//置高电平,为下次传输做准备
                }
        }
}


/****************************************
*名称:void W_1byte(uint8_t RW, uint8_t RS, uint8_t W_data)
*功能:写串口数据,根据RW RS的配置,确定是传输命令还是传输数据
*输入:uint8_t RW, uint8_t RS, uint8_t W_data
*输出:无
******************************************/
void W_1byte(uint8_t RW, uint8_t RS, uint8_t W_data)
{
        uint8_t H_data,L_data,S_ID = 0xf8;  //11111RWRS0
        if(RW == 0)
        {
                S_ID &=~ 0x04;
        }
        else     //if(RW==1)
        {
                S_ID |= 0X04;
        }
        if(RS == 0)
        {
                S_ID &=~ 0x02;
        }                                                                                                                              
        else     //if(RS==1)
        {
                S_ID |= 0X02;
        }
        //以上是根据读写命令以及是发送数据还是命令来组合命令字
        H_data = W_data;
        H_data &= 0xf0;   //屏蔽低4位的数据
        L_data = W_data;    //xxxx0000格式
        L_data &= 0x0f;   //屏蔽高4位的数据
        L_data <<= 4;   //xxxx0000格式
        HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,GPIO_PIN_SET);        //CS = 1; 时能发送
        Write_8bits(S_ID);   //发送命令字S_ID
        Write_8bits(H_data); //发送H_data
        Write_8bits(L_data); //发送L_data
        HAL_GPIO_WritePin(CS_GPIO_Port,CS_Pin,GPIO_PIN_RESET);        //CS = 0; 时能发送
}


/*****************************************
*功能:lcdinit()
*功能:初始化函数
*输入:cmdcode
*输出:无
*****************************************/

void lcdinit(void)
{
       
        HAL_Delay(10);
        W_1byte(0,0,0x30);//功能设置 8位数据,基本指令;
        HAL_Delay(10);
        //W_1byte(0,0,0x02); //地址归位
        //HAL_Delay(10);
        //W_1byte(0,0,0x06); //游标及显示右移一位
        //HAL_Delay(10);
        W_1byte(0,0,0x0c); //显示状态 ON,游标OFF,反白OFF
        HAL_Delay(10);
        W_1byte(0,0,0x01);  //清除显示
        HAL_Delay(10);
}




/******************************************
*名称:void LCD_Wmessage(uint8_t* message,uint8_t address)
*功能:向LCD12864中写入一行数据(因为你不可能每次只发送一字节数据)
*输入:uint8_t* message,uint8_t address
*输出:无
******************************************/

void LCD_Wmessage(uint8_t* message,uint8_t address)
{
        W_1byte(0, 0, address);
        while(*message>0)//这个判断很关键,判断你的内容有没有发完
        {
                W_1byte(0,1,*message); //内核还是发字节函数
                message++; //指针挺好用的。。
        }
}


lcd12864.h


#include "main.h"

#define                        LINE1                0x80 //第一行起始地址,下同
#define                        LINE2                 0x90
#define                        LINE3                 0x88
#define                        LINE4                 0x98

void Write_8bits(uint8_t W_bits);
void W_1byte(uint8_t RW, uint8_t RS, uint8_t W_data);
void lcdinit(void);
void LCD_Wmessage(uint8_t *message,uint8_t address);
main.c


int main(void)
{
  /* USER CODE BEGIN 1 */
        uint8_t dis3[]={"床前明月光,"};
        uint8_t dis4[]={"疑是地上霜,"};
        uint8_t dis5[]={"举头望明月,"};
        uint8_t dis6[]={"低头思故乡。"};
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
        MX_GPIO_Init();
  /* USER CODE BEGIN 2 */
        lcdinit();
  /* USER CODE END 2 */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
        LCD_Wmessage(dis3,LINE1);  
        LCD_Wmessage(dis4,LINE2);
        LCD_Wmessage(dis5,LINE3);
        LCD_Wmessage(dis6,LINE4);
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}




举报

更多回帖

发帖
×
20
完善资料,
赚取积分