打印
[AT32F421]

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

[复制链接]
1458|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如下:

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


使用特权

评论回复
沙发
l63t89|  楼主 | 2022-3-31 16:00 | 只看该作者
    2)配置spi1的时钟、GPIO等详细见代码注释:

void LCD_GPIO_Init(void)
{
   gpio_init_type gpio_init_struct;
   spi_init_type spi_init_struct;
    /* 使能GPIOA GPIOB时钟 */
   crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
   crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
               
/* set default parameter */
   gpio_default_para_init(&gpio_init_struct);

#if SOFTWARE_SPI_ENABLE        //为模拟spi

        /* configure the led gpio */
        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; //加强的输出能力  跟CH582的 输出20mA与5mA的味道差不多,或者是STM32的推挽输出差不多吧。
        gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;             //上拉输出
        gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;                       //输出模式
        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
        gpio_init_struct.gpio_pull = GPIO_PULL_NONE;                        //floating for input, no pull for output 也就是stm32的floating的吧
        gpio_init(GPIOA, &gpio_init_struct);                                
        gpio_bits_set(GPIOA,GPIO_PINS_4|GPIO_PINS_5|GPIO_PINS_7);          //初始为高电平

#else    //为硬件spi         
        gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
        gpio_init_struct.gpio_pull           = GPIO_PULL_UP;
        gpio_init_struct.gpio_mode           = GPIO_MODE_OUTPUT;
        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
        gpio_init_struct.gpio_pins = GPIO_PINS_4;
        gpio_init(GPIOA, &gpio_init_struct);
        
        gpio_bits_set(GPIOA,GPIO_PINS_4);

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

        gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;

        gpio_init_struct.gpio_pull           = GPIO_PULL_DOWN;
        gpio_init_struct.gpio_mode           = GPIO_MODE_MUX;
        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
        gpio_init_struct.gpio_pins = GPIO_PINS_5  ;
        gpio_init(GPIOA, &gpio_init_struct);

        gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;
        gpio_init_struct.gpio_pull           = GPIO_PULL_UP;
        gpio_init_struct.gpio_mode           = GPIO_MODE_MUX;
        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
        gpio_init_struct.gpio_pins = GPIO_PINS_7 | GPIO_PINS_6;
        gpio_init(GPIOA, &gpio_init_struct);

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

        spi_enable(SPI1, TRUE);
        
#endif        
        //配置DC、RES、BLK
        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
        gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
        gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
        gpio_init_struct.gpio_pins = GPIO_PINS_0|GPIO_PINS_1|GPIO_PINS_2;
        gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
        gpio_init(GPIOB, &gpio_init_struct);      
        gpio_bits_set(GPIOB,GPIO_PINS_0|GPIO_PINS_1|GPIO_PINS_2);       
}

使用特权

评论回复
板凳
l63t89|  楼主 | 2022-3-31 16:02 | 只看该作者
3)改发送函数:
/******************************************************************************
      函数说明:LCD串行数据写入函数
      入口数据:dat  要写入的串行数据
      返回值:  无
******************************************************************************/
void LCD_Writ_Bus(uint8_t dat)
{       
       
  gpio_bits_reset( GPIOA, GPIO_PINS_4 ); //CS拉低,开始发送数数
        #if SOFTWARE_SPI_ENABLE        //模拟发送数据
        u8 i;
        for(i=0;i<8;i++)
        {                          
                LCD_SCLK_LOW();
                if(dat&0x80)
                {
                   LCD_MOSI_HIGH();
                }
                else
                {
                   LCD_MOSI_LOW();
                }
                LCD_SCLK_HIGH();
                dat<<=1;
        }
#else   //使用硬件SPI发送
  spi_i2s_data_transmit(SPI1, dat ); //发送数据
  while(spi_i2s_flag_get(SPI1, SPI_I2S_TDBE_FLAG) == RESET) {};  //等待发送完成,我感觉以后要加超时判断,要不会出问题会阻塞在这里
  gpio_bits_set(GPIOA, GPIO_PINS_4 );  //CS释放
#endif
}

使用特权

评论回复
地板
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)

使用特权

评论回复
5
l63t89|  楼主 | 2022-3-31 16:03 | 只看该作者
   5)修改延时函数为rt_thread的rt_thread_mdelay()函数。

编译通过在main函数中添加头文件与显示函数,编译通过就OK了:

使用特权

评论回复
6
l63t89|  楼主 | 2022-3-31 16:04 | 只看该作者

使用特权

评论回复
7
l63t89|  楼主 | 2022-3-31 16:05 | 只看该作者
下载后显示如下图:

使用特权

评论回复
8
l63t89|  楼主 | 2022-3-31 16:06 | 只看该作者
【感受】AT32F425是ARM M4的核心,使用起来跟STM32、N32G45流程是一样的。这次驱动GC9306还是挺轻松的。不过用过沁恒的CH582M后,感觉ARM 配置外设相双RISC-V就复杂很多。AT32F425的在RT_Thread 驱动LCD很流畅。

使用特权

评论回复
9
l63t89|  楼主 | 2022-3-31 16:07 | 只看该作者
【建议】AT32F425没有中文固件库文档,建议官方的固件库文档有中英文的。还有就是开发板的针脚排列不是按顺序的,印刷的字体很小、而且的斜的,特别是夹在中间的,看起来很吃力,建议如果有下一板适当的调整,提高一下舒适度。

使用特权

评论回复
10
846299599| | 2022-6-14 10:54 | 只看该作者
博主有代码分享一下吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

88

主题

776

帖子

1

粉丝