U8G2移植到STM32(GPIO模拟SPI)
1.硬件电路
- 使用STM32C8T6来移植U8G2
- LCD屏,单色12864lcd液晶屏,厂家是深圳思迈微电子,驱动芯片是ST7567,购买链接:https://item.taobao.com/item.htm?spm=a1z09.2.0.0.121d2e8d7OvIb2&id=660349996995&_u=72gg942t051a
LCD屏使用SPI接口,屏资料如下:
- STM32C8T6使用GPIO口模拟SPI来与LCD屏通信,使用的IO口如下:
#define SPI_LCD_CONTROL PAout(0)
#define SPI_LCD_LED_A PAout(6)
#define SPI_PORT_LCD_SCK GPIOA
#define SPI_PIN_LCD_SCK GPIO_Pin_4
#define SPI_PORT_LCD_SDA GPIOA
#define SPI_PIN_LCD_SDA GPIO_Pin_5
#define SPI_PORT_LCD_CS GPIOA
#define SPI_PIN_LCD_CS GPIO_Pin_1
#define SPI_PORT_LCD_DC GPIOA
#define SPI_PIN_LCD_DC GPIO_Pin_3
#define SPI_PORT_LCD_RES GPIOA
#define SPI_PIN_LCD_RES GPIO_Pin_2
2.代码移植
- U8G2源代码下载:https://github.com/olikraus/u8g2
- 将u8g2-master/csrc目录下的代码移植到STM32C8T6的工程目录下。
- u8x8_d_驱动芯片型号.c是不同屏幕的驱动文件,只保留u8x8_d_st7567.c。
- 在keil5中添加u8g2目录和头文件。
- keil5配置好后目录结构如下:
3.代码修改
-
裁剪u8g2_d_setup.c
u8g2_Setup_st7567_jlx12864_1
u8g2_Setup_st7567_jlx12864_2
u8g2_Setup_st7567_jlx12864_f
这三个是使用SPI驱动的代码,删除其它不用的代码。
这三个函数的区别是占用的缓冲区大小不一样,分别是128Byte,256Byte,1024Byte。 -
在u8g2_d_setup.c中添加u8g2初始化代码
void u8g2_init(u8g2_t *u8g2)
{
u8g2_Setup_st7567_jlx12864_f(u8g2, U8G2_R0, u8x8_byte_4wire_sw_spi, u8g2_gpio_and_delay); // 初始化 u8g2 结构体
u8g2_InitDisplay(u8g2);// 根据所选的芯片进行初始化工作,初始化完成后,显示器处于关闭状态
u8g2_SetPowerSave(u8g2, 0); // 唤醒显示器
u8g2_SetContrast(u8g2, 100);//设置对比度
u8g2_ClearBuffer(u8g2);//清除显示缓存
}
-
u8g2_Setup_st7567_jlx12864_f函数参数解析
u8g2: A pointer to the u8g2 structure.
rotation:旋转角度
byte_cb:SPI读写回调函数
gpio_and_delay_cb:SPI GPIO操作及延时函数的回调 -
写gpio_and_delay_cb回调函数
uint8_t u8g2_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
switch(msg)
{
//Initialize SPI peripheral
case U8X8_MSG_GPIO_AND_DELAY_INIT:
s_gpio_spi_init();
break;
//Function which implements a delay, arg_int contains the amount of ms
case U8X8_MSG_DELAY_MILLI:
delay_ms(arg_int);
break;
//Function which delays 10us
case U8X8_MSG_DELAY_10MICRO:
delay_us(arg_int);
break;
//Function which delays 100ns
case U8X8_MSG_DELAY_100NANO:
__NOP();;
break;
//Function to define the logic level of the clockline
case U8X8_MSG_GPIO_SPI_CLOCK:
if(arg_int)
GPIO_SetBits(SPI_PORT_LCD_SCK, SPI_PIN_LCD_SCK);
else
GPIO_ResetBits(SPI_PORT_LCD_SCK, SPI_PIN_LCD_SCK);
break;
//Function to define the logic level of the data line to the display
case U8X8_MSG_GPIO_SPI_DATA:
if(arg_int)
GPIO_SetBits(SPI_PORT_LCD_SDA, SPI_PIN_LCD_SDA);
else
GPIO_ResetBits(SPI_PORT_LCD_SDA, SPI_PIN_LCD_SDA);
break;
// Function to define the logic level of the CS line
case U8X8_MSG_GPIO_CS:
if(arg_int)
GPIO_SetBits(SPI_PORT_LCD_CS, SPI_PIN_LCD_CS);
else
GPIO_ResetBits(SPI_PORT_LCD_CS, SPI_PIN_LCD_CS);
break;
//Function to define the logic level of the Data/ Command line
case U8X8_MSG_GPIO_DC:
if(arg_int)
GPIO_SetBits(SPI_PORT_LCD_DC, SPI_PIN_LCD_DC);
else
GPIO_ResetBits(SPI_PORT_LCD_DC, SPI_PIN_LCD_DC);
break;
//Function to define the logic level of the RESET line
case U8X8_MSG_GPIO_RESET:
if(arg_int)
GPIO_SetBits(SPI_PORT_LCD_RES, SPI_PIN_LCD_RES);
else
GPIO_ResetBits(SPI_PORT_LCD_RES, SPI_PIN_LCD_RES);
break;
default:
return 0; //A message was received which is not implemented, return 0 to indicate an error
}
return 1; // command processed successfully.
}
- u8g2的坐标系如下
- 主函数添加如下代码
void draw(u8g2_t *u8g2)
{
u8g2_SetFontMode(u8g2, 1); /*字体模式选择*/
u8g2_SetFontDirection(u8g2, 0); /*字体方向选择*/
u8g2_SetFont(u8g2, u8g2_font_inb24_mf); /*字库选择*/
u8g2_DrawStr(u8g2, 0, 20, "U");
u8g2_SetFontDirection(u8g2, 1);
u8g2_SetFont(u8g2, u8g2_font_inb30_mn);
u8g2_DrawStr(u8g2, 21,8,"8");
u8g2_SetFontDirection(u8g2, 0);
u8g2_SetFont(u8g2, u8g2_font_inb24_mf);
u8g2_DrawStr(u8g2, 51,30,"g");
u8g2_DrawStr(u8g2, 67,30,"\xb2");
u8g2_DrawHLine(u8g2, 2, 35, 47);
u8g2_DrawHLine(u8g2, 3, 36, 47);
u8g2_DrawVLine(u8g2, 45, 32, 12);
u8g2_DrawVLine(u8g2, 46, 33, 12);
u8g2_SetFont(u8g2, u8g2_font_amstrad_cpc_extended_8r);
u8g2_DrawStr(u8g2, 1,54,"github.x/x/u8g2");
}
int main(void)
{
unsigned int index;
u8g2_t u8g2;
SysTick_Init(72);
GPIO_Configuration();
u8g2_init(&u8g2);
while (1)
{
index++;
if(index%10000)
PBout(12) = ~ PBin(12);
delay_us(100);
u8g2_FirstPage(&u8g2);
do
{
draw(&u8g2);
} while (u8g2_NextPage(&u8g2));
}
}
draw函数是官网上面的一个demo。
- 另外对字体库u8g2_fonts.c进行了裁剪 ,只保留的使用的字体。具体的修改请看源码。
4.移植成功后运行效果
5.备注
项目源码下载:
spi_lcd_u8g2_v01.rar
链接:https://pan.baidu.com/s/1ODQzlX-4O6Z5gBeAOLHorA
提取码:v1ks