打印
[STM32]

分享一个基于STM32F410 HAL库串行驱动LCD12864的学习笔记

[复制链接]
1729|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
说在前面的话:之前老师给我了一块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


#include "stm32f4xx_hal.h"


#include "LCD12864_S.h"

#include "led.h"
#include "Systick.h"

static void Error_Handler(void);
static void SystemClock_Config(void);


int main(void)
{
  HAL_Init();                                               
  /* Configure the system clock to 100 MHz */
        SystemClock_Config();                       
        /*HAL_SYSTICK_Config*/
        init_led();
        LCD12864_GPIO_Init();
        LCD12864_Init();
        led_on;
  while (1)
  {
                        led_toggle;
                        delay_ms(500);
                        LCD12864_Write_String(0,0,"hello,world");
                        LCD12864_Write_String(3,3,"@enderman1");
  }
}

/**
  * [url=home.php?mod=space&uid=247401]@brief[/url]  System Clock Configuration
  *         The system Clock is configured as follow :
  *            System Clock source            = PLL (HSI)
  *            SYSCLK(Hz)                     = 100000000
  *            HCLK(Hz)                       = 100000000
  *            AHB Prescaler                  = 1
  *            APB1 Prescaler                 = 2
  *            APB2 Prescaler                 = 1
  *            HSI Frequency(Hz)              = 16000000
  *            PLL_M                          = 16
  *            PLL_N                          = 200
  *            PLL_P                          = 2
  *            PLL_Q                          = 15
  *            PLL_R                          = 7
  *            VDD(V)                         = 3.3
  *            Main regulator output voltage  = Scale1 mode
  *            Flash Latency(WS)              = 5
  * @param  None
  * @retval None
  */
static void SystemClock_Config(void)
{
  RCC_ClkInitTypeDef RCC_ClkInitStruct;
  RCC_OscInitTypeDef RCC_OscInitStruct;

  /* Enable Power Control clock */
  __HAL_RCC_PWR_CLK_ENABLE();

  /* The voltage scaling allows optimizing the power consumption when the device is
     clocked below the maximum system frequency, to update the voltage scaling value
     regarding system frequency refer to product datasheet.  */
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /* Enable HSI Oscillator and activate PLL with HSI as source */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
        RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = 0x10;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 16;
  RCC_OscInitStruct.PLL.PLLN = 200;                                                //倍频系数
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;                                //6       
  RCC_OscInitStruct.PLL.PLLQ = 15;
  RCC_OscInitStruct.PLL.PLLR = 7;
  
  if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }
  
  /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
     clocks dividers */
  RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  
  if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @param  None
  * @retval None
  */
static void Error_Handler(void)
{
  /* User may add here some code to deal with this error */
  while(1)
  {
  }
}


以上就是所有代码(除了LED)直接复制即可使用,移植的话我想也是比较简单的吧,个人感觉写的比较通俗。




总之,这只是一个简单的驱动代码,另外具体的一些功能还是参考使用手册吧,这些功能都可以写到这个驱动程序里面。
使用手册:
J12864中文液晶使用说明.pdf (662.74 KB)

下次见~

使用特权

评论回复

相关帖子

沙发
mjs0528| | 2019-10-6 21:17 | 只看该作者
谢谢分享,楼主辛苦!

使用特权

评论回复
板凳
554867362| | 2020-3-3 12:37 | 只看该作者
感谢分享

使用特权

评论回复
地板
h472438470| | 2020-4-2 07:16 | 只看该作者
必须点赞

使用特权

评论回复
5
veger| | 2020-4-28 16:33 | 只看该作者
可以将基于STM32F410 HAL库串行驱动LCD12864的工程发一下吗?

使用特权

评论回复
6
Kua_Max| | 2020-4-28 17:22 | 只看该作者
http://114.215.128.55/index.php/post/21.html
之前在这个地方有别人牛人分享的详细的工程和emwin的步骤,可以直接上emwin跑起来

使用特权

评论回复
评论
enderman1 2020-5-21 15:22 回复TA
感谢 
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

71

帖子

12

粉丝