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

[复制链接]
 楼主| enderman1 发表于 2019-8-15 20:44 | 显示全部楼层 |阅读模式
说在前面的话:之前老师给我了一块LCD12864,我知道这玩意儿不便宜然后就兴奋的用51单片机驱动了一下下,还做了一个12864的LOW B示波器,时隔多年我发现网上用stm32驱动这块屏幕的例子不是太详细,于是自己就决定做一做,然后分享一下。

先看一下实现效果吧:


硬件方面:我用的就是普通的LCD12864,至于有的使用手册说的什么3.3V驱动  5V驱动,个人感觉是蒙人的,因为我试了试,发现都一样,需要注意的是这次用的是串行通讯,所以按照使用手册需要把一个地方稍微改一下。下面是截的图片:(上面所说的C4  C5实测无需连接,仅仅需要改一下串口方式即可)

引脚连接的话,连着几个肯定是没问题的,照着图做就行,CS直接接高电平;LED_A LED_K 一定要接!!!


软件方面:

废话不多说,直接上代码:
LCD12864_S.c文件:
  1. //LCD12864串行驱动程序
  2. /*
  3.                 GPIO定义:
  4.                 PA0:串行同步时钟        E(CLK)
  5.                 PA1:串行数据口                R/W(SID)
  6.                                 串行片选(1)        RS(CS)


  7. */
  8. #include "LCD12864_S.h"
  9. #include "Systick.h"
  10. uint8_t const  num_lcd[]={"0123456789 :.-"};

  11. void LCD12864_GPIO_Init(void){
  12.                 GPIO_InitTypeDef lcd_gpio_init;
  13.                 GPIOA_CLK_ON;                                                                                               
  14.                 lcd_gpio_init.Alternate=0;
  15.                 lcd_gpio_init.Mode=GPIO_MODE_OUTPUT_PP;
  16.                 lcd_gpio_init.Pin=CLK_PIN|SID_PIN;
  17.                 lcd_gpio_init.Pull=GPIO_NOPULL;
  18.                 lcd_gpio_init.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
  19.                 HAL_GPIO_Init(LCD_GPIO_PORT,&lcd_gpio_init);
  20.                 HAL_GPIO_WritePin(LCD_GPIO_PORT,CLK_PIN|SID_PIN,GPIO_PIN_SET);

  21. }

  22. void LCD12864_Send_Byte(uint8_t dat){
  23.                 uint8_t i;
  24.                 for(i=0;i<8;i++){
  25.                                 if(dat&0x80){
  26.                                                 SID_H;
  27.                                 }else{
  28.                                                 SID_L;
  29.                                 }
  30.                                 CLK_H;
  31.                                 delay_us(100);
  32.                                 CLK_L;
  33.                                 dat<<=1;
  34.                 }
  35. }


  36. /*
  37.                 cmd=0                写指令
  38.                 cmd=1                写数据

  39. */
  40. void LCD12864_WriteDat(uint8_t cmd,uint8_t ddata){
  41.                 uint8_t con_cmd;
  42.                 uint8_t dat_h,dat_l;
  43.                 if(cmd==1){
  44.                         con_cmd=0xfa;                //写数据
  45.                 }else{
  46.                         con_cmd=0xf8;                //写指令
  47.                 }
  48.                 dat_h=ddata&0xf0;                        //高4位
  49.                 dat_l=(ddata<<4)&0xf0;//低4位
  50.                 LCD12864_Send_Byte(con_cmd);
  51.                 delay_us(100);
  52.                 LCD12864_Send_Byte(dat_h);
  53.                 delay_us(50);
  54.                 LCD12864_Send_Byte(dat_l);
  55.                 delay_us(50);
  56. }
  57. void LCD12864_Init(void){
  58.                 delay_ms(50);
  59.                 LCD12864_WriteDat(0,0x30);//8 位介面,基本指令集
  60.                 LCD12864_WriteDat(0,0x0c);//显示打开,光标关,反白关
  61.                 LCD12864_WriteDat(0,0x01);//清屏,将DDRAM的地址计数器归零  
  62. }
  63. void LCD12864_Clr_Scr(void){        //清屏
  64.                 LCD12864_WriteDat(0,0x01);
  65. }
  66. void LCD12864_Set_XY(uint8_t X,uint8_t Y){
  67.                 uint8_t add;
  68.                 switch(Y){
  69.                         case 0:add=0x80+X;break;
  70.                         case 1:add=0x90+X;break;
  71.                         case 2:add=0x88+X;break;
  72.                         case 3:add=0x98+X;break;
  73.                         default:add=0x80+X;break;
  74.                 }
  75.                 LCD12864_WriteDat(0,add);
  76. }
  77. void LCD12864_Write_String(uint8_t X,uint8_t Y,uint8_t *str){
  78.                 LCD12864_Set_XY(X,Y);
  79.                 while(*str){
  80.                         LCD12864_WriteDat(1,*str);
  81.                         str++;
  82.                         delay_us(10);
  83.                 }
  84. }
  85. void LCD12864_Write_Num(uint8_t str){
  86.                 LCD12864_WriteDat(1,num_lcd[str]);
  87.                 delay_us(10);
  88. }

LCD12864_S.h文件:
  1. //LCD12864串行驱动程序
  2. #ifndef __LCD12864_S_H__
  3. #define __LCD12864_S_H__
  4. #include <stm32f4xx_hal.h>
  5. #define        LCD_GPIO_PORT                                GPIOA

  6. #define GPIOA_CLK_ON                                __HAL_RCC_GPIOA_CLK_ENABLE()
  7. #define CLK_PIN                                                        GPIO_PIN_0
  8. #define SID_PIN                                                        GPIO_PIN_1

  9. #define CLK_H                                                                HAL_GPIO_WritePin(LCD_GPIO_PORT,CLK_PIN,GPIO_PIN_SET)
  10. #define CLK_L                                                                HAL_GPIO_WritePin(LCD_GPIO_PORT,CLK_PIN,GPIO_PIN_RESET)
  11. #define SID_H                                                                HAL_GPIO_WritePin(LCD_GPIO_PORT,SID_PIN,GPIO_PIN_SET)
  12. #define SID_L                                                                HAL_GPIO_WritePin(LCD_GPIO_PORT,SID_PIN,GPIO_PIN_RESET)

  13. void LCD12864_GPIO_Init(void);
  14. void LCD12864_Send_Byte(uint8_t dat);
  15. void LCD12864_WriteDat(uint8_t cmd,uint8_t ddat);
  16. void LCD12864_Init(void);
  17. void LCD12864_Clr_Scr(void);
  18. void LCD12864_Set_XY(uint8_t X,uint8_t Y);
  19. void LCD12864_Write_String(uint8_t X,uint8_t Y,uint8_t *str);
  20. void LCD12864_Write_Num(uint8_t str);

  21. #endif


Systick.c
  1. #include <Systick.h>

  2. void delay_ms(uint16_t nms) //???????
  3. {
  4.                 //HAL_Delay(nms);
  5.                 uint32_t i;
  6.                 SysTick_Config(100000);
  7.                 for(i=0; i<nms; i++)
  8.                 {
  9.                         while( !((SysTick->CTRL) & (1<<16)) );
  10.                 }
  11.                 /* 失能systick */
  12.                 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
  13. }

  14. void delay_us(uint32_t us)
  15. {
  16.     uint32_t J;
  17.                 SysTick_Config(100);                                                //分频16
  18.                 for(J=0; J<us; J++)
  19.                 {
  20.                         while( !((SysTick->CTRL) & (1<<16)) );
  21.                 }
  22.                 /* 失能systick */
  23.                 SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
  24. }









Systick.h

  1. #ifndef __SYSTICK_H_
  2. #define __SYSTICK_H_
  3. #include <stm32f4xx_hal.h>
  4. void delay_ms(uint16_t nms);
  5. void delay_us(uint32_t us);
  6. #endif



main.c


  1. #include "stm32f4xx_hal.h"


  2. #include "LCD12864_S.h"

  3. #include "led.h"
  4. #include "Systick.h"

  5. static void Error_Handler(void);
  6. static void SystemClock_Config(void);


  7. int main(void)
  8. {
  9.   HAL_Init();                                               
  10.   /* Configure the system clock to 100 MHz */
  11.         SystemClock_Config();                       
  12.         /*HAL_SYSTICK_Config*/
  13.         init_led();
  14.         LCD12864_GPIO_Init();
  15.         LCD12864_Init();
  16.         led_on;
  17.   while (1)
  18.   {
  19.                         led_toggle;
  20.                         delay_ms(500);
  21.                         LCD12864_Write_String(0,0,"hello,world");
  22.                         LCD12864_Write_String(3,3,"@enderman1");
  23.   }
  24. }

  25. /**
  26.   * [url=home.php?mod=space&uid=247401]@brief[/url]  System Clock Configuration
  27.   *         The system Clock is configured as follow :
  28.   *            System Clock source            = PLL (HSI)
  29.   *            SYSCLK(Hz)                     = 100000000
  30.   *            HCLK(Hz)                       = 100000000
  31.   *            AHB Prescaler                  = 1
  32.   *            APB1 Prescaler                 = 2
  33.   *            APB2 Prescaler                 = 1
  34.   *            HSI Frequency(Hz)              = 16000000
  35.   *            PLL_M                          = 16
  36.   *            PLL_N                          = 200
  37.   *            PLL_P                          = 2
  38.   *            PLL_Q                          = 15
  39.   *            PLL_R                          = 7
  40.   *            VDD(V)                         = 3.3
  41.   *            Main regulator output voltage  = Scale1 mode
  42.   *            Flash Latency(WS)              = 5
  43.   * @param  None
  44.   * @retval None
  45.   */
  46. static void SystemClock_Config(void)
  47. {
  48.   RCC_ClkInitTypeDef RCC_ClkInitStruct;
  49.   RCC_OscInitTypeDef RCC_OscInitStruct;

  50.   /* Enable Power Control clock */
  51.   __HAL_RCC_PWR_CLK_ENABLE();

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

  56.   /* Enable HSI Oscillator and activate PLL with HSI as source */
  57.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  58.         RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  59.   RCC_OscInitStruct.HSICalibrationValue = 0x10;
  60.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  61.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  62.   RCC_OscInitStruct.PLL.PLLM = 16;
  63.   RCC_OscInitStruct.PLL.PLLN = 200;                                                //倍频系数
  64.   RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;                                //6       
  65.   RCC_OscInitStruct.PLL.PLLQ = 15;
  66.   RCC_OscInitStruct.PLL.PLLR = 7;
  67.   
  68.   if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  69.   {
  70.     Error_Handler();
  71.   }
  72.   
  73.   /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
  74.      clocks dividers */
  75.   RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
  76.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  77.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  78.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;  
  79.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  
  80.   if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK)
  81.   {
  82.     Error_Handler();
  83.   }
  84. }

  85. /**
  86.   * @brief  This function is executed in case of error occurrence.
  87.   * @param  None
  88.   * @retval None
  89.   */
  90. static void Error_Handler(void)
  91. {
  92.   /* User may add here some code to deal with this error */
  93.   while(1)
  94.   {
  95.   }
  96. }


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




总之,这只是一个简单的驱动代码,另外具体的一些功能还是参考使用手册吧,这些功能都可以写到这个驱动程序里面。
使用手册:


下次见~

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
mjs0528 发表于 2019-10-6 21:17 | 显示全部楼层
谢谢分享,楼主辛苦!
554867362 发表于 2020-3-3 12:37 | 显示全部楼层
感谢分享
h472438470 发表于 2020-4-2 07:16 | 显示全部楼层
必须点赞
veger 发表于 2020-4-28 16:33 | 显示全部楼层
可以将基于STM32F410 HAL库串行驱动LCD12864的工程发一下吗?
Kua_Max 发表于 2020-4-28 17:22 | 显示全部楼层
http://114.215.128.55/index.php/post/21.html
之前在这个地方有别人牛人分享的详细的工程和emwin的步骤,可以直接上emwin跑起来

评论

感谢  发表于 2020-5-21 15:22
您需要登录后才可以回帖 登录 | 注册

本版积分规则

11

主题

71

帖子

12

粉丝
快速回复 在线客服 返回列表 返回顶部