说在前面的话:之前老师给我了一块LCD12864,我知道这玩意儿不便宜然后就兴奋的用51单片机驱动了一下下,还做了一个12864的LOW B示波器,时隔多年我发现网上用stm32驱动这块屏幕的例子不是太详细,于是自己就决定做一做,然后分享一下。
先看一下实现效果吧:
硬件方面:我用的就是普通的LCD12864,至于有的使用手册说的什么3.3V驱动 5V驱动,个人感觉是蒙人的,因为我试了试,发现都一样,需要注意的是这次用的是串行通讯,所以按照使用手册需要把一个地方稍微改一下。下面是截的图片:(上面所说的C4 C5实测无需连接,仅仅需要改一下串口方式即可)
引脚连接的话,连着几个肯定是没问题的,照着图做就行,CS直接接高电平;LED_A LED_K 一定要接!!!
软件方面:
废话不多说,直接上代码:
LCD12864_S.c文件:
- //LCD12864串行驱动程序
- /*
- GPIO定义:
- PA0:串行同步时钟 E(CLK)
- PA1:串行数据口 R/W(SID)
- 串行片选(1) RS(CS)
- */
- #include "LCD12864_S.h"
- #include "Systick.h"
- uint8_t const num_lcd[]={"0123456789 :.-"};
- void LCD12864_GPIO_Init(void){
- GPIO_InitTypeDef lcd_gpio_init;
- GPIOA_CLK_ON;
- lcd_gpio_init.Alternate=0;
- lcd_gpio_init.Mode=GPIO_MODE_OUTPUT_PP;
- lcd_gpio_init.Pin=CLK_PIN|SID_PIN;
- lcd_gpio_init.Pull=GPIO_NOPULL;
- lcd_gpio_init.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
- HAL_GPIO_Init(LCD_GPIO_PORT,&lcd_gpio_init);
- HAL_GPIO_WritePin(LCD_GPIO_PORT,CLK_PIN|SID_PIN,GPIO_PIN_SET);
- }
- void LCD12864_Send_Byte(uint8_t dat){
- uint8_t i;
- for(i=0;i<8;i++){
- if(dat&0x80){
- SID_H;
- }else{
- SID_L;
- }
- CLK_H;
- delay_us(100);
- CLK_L;
- dat<<=1;
- }
- }
- /*
- cmd=0 写指令
- cmd=1 写数据
- */
- void LCD12864_WriteDat(uint8_t cmd,uint8_t ddata){
- uint8_t con_cmd;
- uint8_t dat_h,dat_l;
- if(cmd==1){
- con_cmd=0xfa; //写数据
- }else{
- con_cmd=0xf8; //写指令
- }
- dat_h=ddata&0xf0; //高4位
- dat_l=(ddata<<4)&0xf0;//低4位
- LCD12864_Send_Byte(con_cmd);
- delay_us(100);
- LCD12864_Send_Byte(dat_h);
- delay_us(50);
- LCD12864_Send_Byte(dat_l);
- delay_us(50);
- }
- void LCD12864_Init(void){
- delay_ms(50);
- LCD12864_WriteDat(0,0x30);//8 位介面,基本指令集
- LCD12864_WriteDat(0,0x0c);//显示打开,光标关,反白关
- LCD12864_WriteDat(0,0x01);//清屏,将DDRAM的地址计数器归零
- }
- void LCD12864_Clr_Scr(void){ //清屏
- LCD12864_WriteDat(0,0x01);
- }
- void LCD12864_Set_XY(uint8_t X,uint8_t Y){
- uint8_t add;
- switch(Y){
- case 0:add=0x80+X;break;
- case 1:add=0x90+X;break;
- case 2:add=0x88+X;break;
- case 3:add=0x98+X;break;
- default:add=0x80+X;break;
- }
- LCD12864_WriteDat(0,add);
- }
- void LCD12864_Write_String(uint8_t X,uint8_t Y,uint8_t *str){
- LCD12864_Set_XY(X,Y);
- while(*str){
- LCD12864_WriteDat(1,*str);
- str++;
- delay_us(10);
- }
- }
- void LCD12864_Write_Num(uint8_t str){
- LCD12864_WriteDat(1,num_lcd[str]);
- delay_us(10);
- }
LCD12864_S.h文件:
- //LCD12864串行驱动程序
- #ifndef __LCD12864_S_H__
- #define __LCD12864_S_H__
- #include <stm32f4xx_hal.h>
- #define LCD_GPIO_PORT GPIOA
- #define GPIOA_CLK_ON __HAL_RCC_GPIOA_CLK_ENABLE()
- #define CLK_PIN GPIO_PIN_0
- #define SID_PIN GPIO_PIN_1
- #define CLK_H HAL_GPIO_WritePin(LCD_GPIO_PORT,CLK_PIN,GPIO_PIN_SET)
- #define CLK_L HAL_GPIO_WritePin(LCD_GPIO_PORT,CLK_PIN,GPIO_PIN_RESET)
- #define SID_H HAL_GPIO_WritePin(LCD_GPIO_PORT,SID_PIN,GPIO_PIN_SET)
- #define SID_L HAL_GPIO_WritePin(LCD_GPIO_PORT,SID_PIN,GPIO_PIN_RESET)
- void LCD12864_GPIO_Init(void);
- void LCD12864_Send_Byte(uint8_t dat);
- void LCD12864_WriteDat(uint8_t cmd,uint8_t ddat);
- void LCD12864_Init(void);
- void LCD12864_Clr_Scr(void);
- void LCD12864_Set_XY(uint8_t X,uint8_t Y);
- void LCD12864_Write_String(uint8_t X,uint8_t Y,uint8_t *str);
- void LCD12864_Write_Num(uint8_t str);
- #endif
Systick.c
- #include <Systick.h>
- void delay_ms(uint16_t nms) //???????
- {
- //HAL_Delay(nms);
- uint32_t i;
- SysTick_Config(100000);
- for(i=0; i<nms; i++)
- {
- while( !((SysTick->CTRL) & (1<<16)) );
- }
- /* 失能systick */
- SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
- }
- void delay_us(uint32_t us)
- {
- uint32_t J;
- SysTick_Config(100); //分频16
- for(J=0; J<us; J++)
- {
- while( !((SysTick->CTRL) & (1<<16)) );
- }
- /* 失能systick */
- SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
- }
Systick.h
- #ifndef __SYSTICK_H_
- #define __SYSTICK_H_
- #include <stm32f4xx_hal.h>
- void delay_ms(uint16_t nms);
- void delay_us(uint32_t us);
- #endif
main.c
以上就是所有代码(除了LED)直接复制即可使用,移植的话我想也是比较简单的吧,个人感觉写的比较通俗。
总之,这只是一个简单的驱动代码,另外具体的一些功能还是参考使用手册吧,这些功能都可以写到这个驱动程序里面。
使用手册:
下次见~
|