[AT32F421] 【AT-START-F425测评】SPI驱动LCD屏

[复制链接]
1727|9
 楼主| l63t89 发表于 2022-3-31 15:59 | 显示全部楼层 |阅读模式

【前言】LCD屏是单片机常用的外设。GC9306是一款240*320的彩色显示屏,这次是用spi1驱动它,也是我学习AT32F425的spi外设的题目之一。

【步聚】1、先下载查看了AT32F425数据手册。了解spi1的驱动IO是哪些。用于LCD屏的CS、DC、RES、BLK的普通IO是如何驱动的。

              2、查看了spi1的驱动示例,学习如何配置spi1为主从模式。

              3、上网学习其他网友的驱动LCD屏的例子。学习他们配置外设的方法。

              4、用我原来在CH582M的驱动拷贝过来用在AT32F425的工程上。

【具体过程】

             1、在RT_Thread Studio的工程目录下面新建一个drives的工程目录,把我原来用在CH582上面的5个文件lcd_init.c、lcd_init.h、lcd.c、lcd.h、lcdfont.h拷贝到这个目录下面。其实单片机学习就象堆积木,用的外设多了,哪怕换一款芯片,使用起来也方便,使用起来没有象以前从头开始、查资料、找驱动===。

             2、根据上次驱动gc9306的经验,拷贝文件过来,只需要修改几个参数就行了:1、屏的init,这里主要是改写spi发送数据的这个LCD_Init函数。 2、修改DC、RES、CS、BLK四个IO的驱动(宏配置)。

            1)定义驱动的IO如下:

  1. //  生成日期   : 2022-3-27
  2. //  最近修改   :
  3. //  功能描述   :AT32F425 GC9306
  4. //              说明:
  5. //              ----------------------------------------------------------------
  6. //              GND   电源地
  7. //              VCC   3.3v电源
  8. //              SCL   PA5(SCLK)
  9. //              SDA   PA7(MOSI)
  10. //              RES   PB0                //复位
  11. //              DC    PB1                //命令、数据选择位
  12. //              CS    PA4                //spi片选
  13. //              BLK   PB2                //背光
  14. //              ----------------------------------------------------------------


 楼主| l63t89 发表于 2022-3-31 16:00 | 显示全部楼层
    2)配置spi1的时钟、GPIO等详细见代码注释:

  1. void LCD_GPIO_Init(void)
  2. {
  3.    gpio_init_type gpio_init_struct;
  4.    spi_init_type spi_init_struct;
  5.     /* 使能GPIOA GPIOB时钟 */
  6.    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  7.    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
  8.                
  9. /* set default parameter */
  10.    gpio_default_para_init(&gpio_init_struct);

  11. #if SOFTWARE_SPI_ENABLE        //为模拟spi

  12.         /* configure the led gpio */
  13.         gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; //加强的输出能力  跟CH582的 输出20mA与5mA的味道差不多,或者是STM32的推挽输出差不多吧。
  14.         gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;             //上拉输出
  15.         gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;                       //输出模式
  16.         gpio_init_struct.gpio_pins = GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_7;    //选择输出的IO 分别为4、5、7脚  是不是由于专利的问题 我看到这个STM32:GPIO_PIN_0,CH582的GPIO_Pin_0
  17.         gpio_init_struct.gpio_pull = GPIO_PULL_NONE;                        //floating for input, no pull for output 也就是stm32的floating的吧
  18.         gpio_init(GPIOA, &gpio_init_struct);                                
  19.         gpio_bits_set(GPIOA,GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_7);          //初始为高电平

  20. #else    //为硬件spi         
  21.         gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  22.         gpio_init_struct.gpio_pull           = GPIO_PULL_UP;
  23.         gpio_init_struct.gpio_mode           = GPIO_MODE_OUTPUT;
  24.         gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  25.         gpio_init_struct.gpio_pins = GPIO_PINS_4;
  26.         gpio_init(GPIOA, &gpio_init_struct);
  27.         
  28.         gpio_bits_set(GPIOA,GPIO_PINS_4);

  29.         gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE5, GPIO_MUX_0);  //这个muxing 百度翻译也整不明白,是不是管角复用的意思?看到数据手册是乎是5的第1功能为SPI1
  30.         gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE6, GPIO_MUX_0);
  31.         gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE7, GPIO_MUX_0);
  32.         gpio_default_para_init(&gpio_init_struct);

  33.         gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;

  34.         gpio_init_struct.gpio_pull           = GPIO_PULL_DOWN;
  35.         gpio_init_struct.gpio_mode           = GPIO_MODE_MUX;
  36.         gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  37.         gpio_init_struct.gpio_pins = GPIO_PINS_5  ;
  38.         gpio_init(GPIOA, &gpio_init_struct);

  39.         gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
  40.         gpio_init_struct.gpio_pull           = GPIO_PULL_UP;
  41.         gpio_init_struct.gpio_mode           = GPIO_MODE_MUX;
  42.         gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  43.         gpio_init_struct.gpio_pins = GPIO_PINS_7 | GPIO_PINS_6;
  44.         gpio_init(GPIOA, &gpio_init_struct);

  45.         crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);   //使能SPI1的时钟
  46.   
  47.         spi_default_para_init(&spi_init_struct);               //复位SPI1
  48.         spi_init_struct.transmission_mode = SPI_TRANSMIT_HALF_DUPLEX_TX;    //单线双向半双工模式传输(slben=1和slbtd=1)  
  49.         spi_init_struct.master_slave_mode = SPI_MODE_MASTER;                //主机模式
  50.         spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_2;                //2分频,有空测一下频率是多少
  51.         spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;         //MSB 高位在前?     
  52.         spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;                     //一帧为8位
  53.         spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;  //sck在空闲状态下保持高
  54.         spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;       //数据捕获从第二个时钟边缘开始
  55.         spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;  //CS由软件控制
  56.         spi_init(SPI1, &spi_init_struct);

  57.         spi_enable(SPI1, TRUE);
  58.         
  59. #endif        
  60.         //配置DC、RES、BLK
  61.         gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  62.         gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
  63.         gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  64.         gpio_init_struct.gpio_pins = GPIO_PINS_0|GPIO_PINS_1|GPIO_PINS_2;
  65.         gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  66.         gpio_init(GPIOB, &gpio_init_struct);      
  67.         gpio_bits_set(GPIOB,GPIO_PINS_0|GPIO_PINS_1|GPIO_PINS_2);       
  68. }
 楼主| l63t89 发表于 2022-3-31 16:02 | 显示全部楼层
3)改发送函数:
  1. /******************************************************************************
  2.       函数说明:LCD串行数据写入函数
  3.       入口数据:dat  要写入的串行数据
  4.       返回值:  无
  5. ******************************************************************************/
  6. void LCD_Writ_Bus(uint8_t dat)
  7. {       
  8.        
  9.   gpio_bits_reset( GPIOA, GPIO_PINS_4 ); //CS拉低,开始发送数数
  10.         #if SOFTWARE_SPI_ENABLE        //模拟发送数据
  11.         u8 i;
  12.         for(i=0;i<8;i++)
  13.         {                          
  14.                 LCD_SCLK_LOW();
  15.                 if(dat&0x80)
  16.                 {
  17.                    LCD_MOSI_HIGH();
  18.                 }
  19.                 else
  20.                 {
  21.                    LCD_MOSI_LOW();
  22.                 }
  23.                 LCD_SCLK_HIGH();
  24.                 dat<<=1;
  25.         }
  26. #else   //使用硬件SPI发送
  27.   spi_i2s_data_transmit(SPI1, dat ); //发送数据
  28.   while(spi_i2s_flag_get(SPI1, SPI_I2S_TDBE_FLAG) == RESET) {};  //等待发送完成,我感觉以后要加超时判断,要不会出问题会阻塞在这里
  29.   gpio_bits_set(GPIOA, GPIO_PINS_4 );  //CS释放
  30. #endif
  31. }
 楼主| l63t89 发表于 2022-3-31 16:02 | 显示全部楼层
     4)修改DC、RES、BLK的宏配置:
#define RES_PIN  GPIO_PINS_0
#define DC_PIN   GPIO_PINS_1
#define BLK_PIN  GPIO_PINS_2

#define CS_PIN   GPIO_PINS_4
//-----------------LCD端口定义----------------

#define LCD_CS_Clr   gpio_bits_reset(GPIOA, CS_PIN)//CS
#define LCD_CS_Set   gpio_bits_set(GPIOA, CS_PIN)

#define LCD_RES_Clr  gpio_bits_reset(GPIOB, RES_PIN)//RES
#define LCD_RES_Set  gpio_bits_set(GPIOB, RES_PIN)

#define LCD_DC_Clr   gpio_bits_reset(GPIOB, DC_PIN)//DC
#define LCD_DC_Set   gpio_bits_set(GPIOB,DC_PIN)

#define LCD_BLK_Clr  gpio_bits_reset(GPIOB,BLK_PIN)//BLK
#define LCD_BLK_Set  gpio_bits_set(GPIOB,BLK_PIN)

#define LCD_SCLK_LOW() gpio_bits_reset(GPIOA, GPIO_PINS_5)
#define LCD_SCLK_HIGH() gpio_bits_set(GPIOA, GPIO_PINS_5)

#define LCD_MOSI_LOW() gpio_bits_reset(GPIOA, GPIO_PINS_7)
#define LCD_MOSI_HIGH() gpio_bits_set(GPIOA, GPIO_PINS_7)
 楼主| l63t89 发表于 2022-3-31 16:03 | 显示全部楼层
   5)修改延时函数为rt_thread的rt_thread_mdelay()函数。

编译通过在main函数中添加头文件与显示函数,编译通过就OK了:
 楼主| l63t89 发表于 2022-3-31 16:04 | 显示全部楼层
 楼主| l63t89 发表于 2022-3-31 16:05 | 显示全部楼层
下载后显示如下图:
246896245608a66997.png
 楼主| l63t89 发表于 2022-3-31 16:06 | 显示全部楼层
【感受】AT32F425是ARM M4的核心,使用起来跟STM32、N32G45流程是一样的。这次驱动GC9306还是挺轻松的。不过用过沁恒的CH582M后,感觉ARM 配置外设相双RISC-V就复杂很多。AT32F425的在RT_Thread 驱动LCD很流畅。
 楼主| l63t89 发表于 2022-3-31 16:07 | 显示全部楼层
【建议】AT32F425没有中文固件库文档,建议官方的固件库文档有中英文的。还有就是开发板的针脚排列不是按顺序的,印刷的字体很小、而且的斜的,特别是夹在中间的,看起来很吃力,建议如果有下一板适当的调整,提高一下舒适度。
846299599 发表于 2022-6-14 10:54 | 显示全部楼层
博主有代码分享一下吗
您需要登录后才可以回帖 登录 | 注册

本版积分规则

101

主题

1077

帖子

1

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