STM32——FSMC接口驱动调试ATK-MD0700 模块
本文内容主要记录自己调试正点原子FSMC接口驱动LCD屏代码的过程。
硬件平台
- 正点原子战舰V3开发板(主控STM32F103ZET6)
- 正点原子LCD电容触摸屏(ATK-MD0700 V2模块)
(模块驱动代码来自正点原子例程)
使能FSMC时钟和IO口时钟
FSMC 接口有 34 个引脚,使用到了 GPIOD、GPIOE、GPIOF、GPIOG ,需要使能这几个 IO 口的时钟。
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE); // 使能FSMC时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD |
RCC_APB2Periph_GPIOE |
RCC_APB2Periph_GPIOF |
RCC_APB2Periph_GPIOG, ENABLE);
FSMC接口与GPIO引脚的对照如下:
LCD模块需要为 GPIO RS、CS、RD、WR、D0~D15 这几个引脚初始化对应的 GPIO 引脚。配置引脚模式为 复用推挽输出 ,设置为高速率的 50M Hz 。
// Example:
GPIO_InitTypeDef gpio_init_struct = {0};
/* 初始化RS引脚 */
gpio_init_struct.GPIO_Pin = GPIOG;
gpio_init_struct.GPIO_Mode = GPIO_Mode_AF_PP;
gpio_init_struct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOG, &gpio_init_struct);
配置FSMC接口
调试目标是利用 FSMC 接口将 LCD 屏内部存储视为 SRAM 进行操作,需要设置存储类型为 SRAM ,配置为使用 Bank1 Sector4 。
工作模式选择异步方式下的 Module A,并允许对 SRAM 的写操作,设置字长为 16 bit。
/* FSMC 配置 */
FSMC_NSInitStructure.FSMC_Bank = ATK_MD0700_FSMC_BANK; // 使用bank第4区
FSMC_NSInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; // 不复用数据地址
FSMC_NSInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM; // SRAM
FSMC_NSInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
FSMC_NSInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
FSMC_NSInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
FSMC_NSInitStructure.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable;
FSMC_NSInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
FSMC_NSInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
FSMC_NSInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; // 存储器写使能
FSMC_NSInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
FSMC_NSInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable;
FSMC_NSInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
// 读时序配置,单位为 HCLK
readWriteTiming.FSMC_AddressSetupTime = 0x00; // 地址建立时间
readWriteTiming.FSMC_DataSetupTime = 0x0F; // 数据保存时间
readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A; // 模式 A
// 写时序配置,单位为 HCLK
writeTiming.FSMC_AddressSetupTime = 0x00; // 地址建立时间
writeTiming.FSMC_DataSetupTime = 0x01; // 数据保存时间
writeTiming.FSMC_BusTurnAroundDuration = 0x00;
writeTiming.FSMC_AccessMode = FSMC_AccessMode_A; // 模式A
FSMC_NSInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;
FSMC_NSInitStructure.FSMC_WriteTimingStruct = &writeTiming;
FSMC_NORSRAMInit(&FSMC_NSInitStructure); // 初始化FSMC配置
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE); // 使能Bank1
对外开放的API
LCD屏初始化
uint8_t atk_md0700_init(void);
获取LCD屏分辨率信息
uint16_t atk_md0700_get_lcd_width(void); /* 获取ATK-MD0700模块LCD宽度 */
uint16_t atk_md0700_get_lcd_height(void); /* 获取ATK-MD0700模块LCD高度 */
显示设置
void atk_md0700_backlight_config(uint8_t pwm); // 调节背光,范围在 [0, 255],亮度由暗到亮
void atk_md0700_display_on(void); /* 开启ATK-MD0700模块LCD显示 */
void atk_md0700_display_off(void); /* 关闭显示*/
图案绘制
//区域填充,起点坐标(xs,ys),终点坐标(xe,ye),向两点形成的区域填充颜色color
void atk_md0700_fill(uint16_t xs, uint16_t ys, uint16_t xe, uint16_t ye, uint16_t color);
// 清屏,全屏填充为颜色color
void atk_md0700_clear(uint16_t color);
// 在(x,y)处绘制颜色为color的点
void atk_md0700_draw_point(uint16_t x, uint16_t y, uint16_t color);
// 读取点(x,y)的颜色
uint16_t atk_md0700_read_point(uint16_t x, uint16_t y);
// 在(x1,y1)、(x2,y2)两点之间绘制直线,并染色为color
void atk_md0700_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
// 绘制点(x1,y1)、(x2,y2)形成的矩形框,染色为color
void atk_md0700_draw_rect(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color);
// 以点(x,y)为圆心,r为半径,画圆,圆周线框的颜色为color
void atk_md0700_draw_circle(uint16_t x, uint16_t y, uint16_t r, uint16_t color);
显示字符
void atk_md0700_show_char(uint16_t x, uint16_t y,
char ch, atk_md0700_lcd_font_t font,
uint16_t color); /* ATK-MD0700模块LCD显示1个字符 */
void atk_md0700_show_string(uint16_t x, uint16_t y,
uint16_t width, uint16_t height,
char *str, atk_md0700_lcd_font_t font,
uint16_t color); /* ATK-MD0700模块LCD显示字符串 */
void atk_md0700_show_xnum(uint16_t x, uint16_t y,
uint32_t num, uint8_t len,
atk_md0700_num_mode_t mode, atk_md0700_lcd_font_t font,
uint16_t color); /* ATK-MD0700模块LCD显示数字,可控制显示高位0 */
void atk_md0700_show_num(uint16_t x, uint16_t y,
uint32_t num, uint8_t len,
atk_md0700_lcd_font_t font,
uint16_t color); /* ATK-MD0700模块LCD显示数字,不显示高位0 */
void atk_md0700_show_pic(uint16_t x, uint16_t y,
uint16_t width, uint16_t height,
uint8_t *pic); /* ATK-MD0700模块LCD显示图片 */