本帖最后由 sujingliang 于 2024-4-19 16:20 编辑
Ai-M61-32SU 有4M flash,可以装载一个完整的200多K的GB2312_80字库。本文实现字库装载并通过驱动ST7735屏幕,显示文字。
一、将gb2312_80.bin(字库文件)烧录到Ai-M61-32SU中
1、将gb2312_80.bin放到工程的根目录
2、修改flash_prog_cfg.ini文件,增加了partition和media部分
- [cfg]
- # 0: no erase, 1:programmed section erase, 2: chip erase
- erase = 1
- # skip mode set first para is skip addr, second para is skip len, multi-segment region with ; separated
- skip_mode = 0x0, 0x0
- # 0: not use isp mode, #1: isp mode
- boot2_isp_mode = 0
- [FW]
- filedir = ./build/build_out/gpio*_$(CHIPNAME).bin
- address = 0x000000
- [partition]
- filedir = ./build/build_out/partition.bin
- address = 0xE000
- [media]
- filedir = ./gb2312_80.bin
- address = @partition
复制代码
gb2312_80.bin的起始地址由partition.bin决定。
partition.bin的参数由aithinker_Ai-M6X_SDK\bsp\board\bl616dk\config\partition_cfg_4M.toml决定。partition_cfg_4M.toml有如下内容:
- [[pt_entry]]
- type = 2
- name = "media"
- device = 0
- address0 = 0x378000
- size0 = 0x71000
- address1 = 0
- size1 = 0
复制代码
所以meida 分区起始地址为0x378000,空间为0X71000,大概500k。
3、程序烧录时顺便把字库也烧进区
这样就可以把gb2312_80.bin烧录到0x378000
二、 用于LCD显示及字库读取的程序main.c
- #include "bflb_gpio.h"
- #include "bflb_uart.h"
- #include "board.h"
- #include "lcd.h"
- #include "hzk.h"
- struct bflb_device_s *uartx;
- struct bflb_device_s *gpio;
- void uart_isr(int irq, void *arg)
- {
- uint32_t intstatus = bflb_uart_get_intstatus(uartx);
- if (intstatus & UART_INTSTS_RX_FIFO) {
- printf("rx fifo\r\n");
- while (bflb_uart_rxavailable(uartx)) {
- printf("0x%02x\r\n", bflb_uart_getchar(uartx));
- }
- bflb_uart_feature_control(uartx, UART_CMD_SET_RTS_VALUE, 1);
- }
- if (intstatus & UART_INTSTS_RTO) {
- printf("rto\r\n");
- while (bflb_uart_rxavailable(uartx)) {
- printf("0x%02x\r\n", bflb_uart_getchar(uartx));
- }
- bflb_uart_int_clear(uartx, UART_INTCLR_RTO);
- }
- }
- void uart_init(void)
- {
- uartx = bflb_device_get_by_name(DEFAULT_TEST_UART);
- struct bflb_uart_config_s cfg;
- cfg.baudrate = 115200;
- cfg.data_bits = UART_DATA_BITS_8;
- cfg.stop_bits = UART_STOP_BITS_1;
- cfg.parity = UART_PARITY_NONE;
- cfg.flow_ctrl = 0;
- cfg.tx_fifo_threshold = 7;
- cfg.rx_fifo_threshold = 7;
- bflb_uart_init(uartx, &cfg);
- bflb_uart_rxint_mask(uartx, false);
- bflb_irq_attach(uartx->irq_num, uart_isr, NULL);
- bflb_irq_enable(uartx->irq_num);
- bflb_uart_feature_control(uartx, UART_CMD_SET_SW_RTS_CONTROL, true);
- bflb_uart_feature_control(uartx, UART_CMD_SET_RTS_VALUE, 0);
- }
- int main(void)
- {
- board_init();
- board_uartx_gpio_init();
- uart_init();
- lcd_init();
- lcd_clear(LCD_COLOR_RGB565(255,0,0));
- gpio = bflb_device_get_by_name("gpio");
- printf("gpio output\r\n");
- bflb_gpio_init(gpio, GPIO_PIN_17, GPIO_OUTPUT | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_0);
- bflb_gpio_set(gpio, GPIO_PIN_17);
- GUI_Write16CnCharMatrix(0,32,(uint8_t*)"蒹葭苍苍白露为霜",LCD_COLOR_RGB565(255,255,255),LCD_COLOR_RGB565(255,0,0));
- GUI_Write16CnCharMatrix(0,52,(uint8_t*)"所谓伊人在水一方",LCD_COLOR_RGB565(255,255,255),LCD_COLOR_RGB565(255,0,0));
- GUI_Write16CnCharMatrix(0,72,(uint8_t*)"溯洄从之道阻且长",LCD_COLOR_RGB565(255,255,255),LCD_COLOR_RGB565(255,0,0));
- GUI_Write16CnCharMatrix(0,92,(uint8_t*)"溯游从之宛在水中央",LCD_COLOR_RGB565(255,255,255),LCD_COLOR_RGB565(255,0,0));
- while (1) {
- }
- }
复制代码
hzk.h
- #ifndef ___HZK_H___
- #define ___HZK_H___
- void GUI_Write16CnCharMatrix(unsigned char x, unsigned char y, uint8_t *cn, unsigned short wordColor, unsigned short backColor);
- #endif
复制代码 hzk.c
- #include "bflb_flash.h"
- #include "lcd.h"
- #include "hzk.h"
- uint32_t FLASH_ADDR_BASE=0x378000;
- uint8_t MatrixBuff[32];
- void getMatrix(const unsigned short nmCode)
- {
- uint8_t i;
- uint32_t offset;
- unsigned char GBH,GBL;
- unsigned short nm=nmCode;
- GBH=nm>>8;
- GBL=nm;
- if(GBH>=0xb0)
- {
- offset=((GBH-0xa7)*94+GBL-0xa1)*32;
- }else
- {
- offset=((GBH-0xa1)*94+GBL-0xa1)*32;
- }
- bflb_flash_read(FLASH_ADDR_BASE+offset+i, MatrixBuff, sizeof(MatrixBuff));
- }
- void GUI_Write16CnCharMatrix(unsigned char x, unsigned char y, uint8_t *cn, unsigned short wordColor, unsigned short backColor)
- {
- uint8_t i, j, wordNum;
- uint16_t zm;
- uint16_t color;
- while (*cn != '\0')
- {
- //setXY(x, y, x+15, y+15);
- zm=*cn;
- zm<<=8;
- zm|=*(cn+1);
- getMatrix(zm);
- for(i=0; i<32; i++)
- { //MSK的位数
- color=MatrixBuff[i];
- for(j=0;j<8;j++)
- {
- if((color&0x80)==0x80)
- {
- //lcd_write_data_word(wordColor);
- if(i%2==0) lcd_draw_point(x+j,y+i/2,wordColor);
- else lcd_draw_point(x+j+8,y+i/2,wordColor);
- }
- else
- {
- //lcd_write_data_word(backColor);
- if(i%2==0) lcd_draw_point(x+j,y+i/2,backColor);
- else lcd_draw_point(x+j+8,y+i/2,backColor);
- }
- color<<=1;
- }//for(j=0;j<8;j++)结束
- }
- cn += 2;
- x += 16;
- }
- }
复制代码 为了支持LCD显示,在aithinker_Ai-M6X_SDK\bsp\common\lcd\spi中添加了2个文件:st7735s_spi.h
- /**
- * @file st7735s.h
- * @brief
- *
- * Copyright (c) 2021 Bouffalolab team
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- */
- #ifndef _ST7735S_SPI_H_
- #define _ST7735S_SPI_H_
- #include "../lcd_conf.h"
- #if defined LCD_SPI_ST7735S
- /* Do not modify the following */
- #define ST7735S_SPI_COLOR_DEPTH 16
- typedef struct {
- uint8_t cmd; /* 0xFF : delay(databytes)ms */
- const char *data;
- uint8_t databytes; /* Num of data in data; or delay time */
- } st7735s_spi_init_cmd_t;
- typedef uint16_t st7735s_spi_color_t;
- int st7735s_spi_init();
- void st7735s_spi_async_callback_enable(bool enable);
- void st7735s_spi_async_callback_register(void (*callback)(void));
- int st7735s_spi_set_dir(uint8_t dir, uint8_t mir_flag);
- void st7735s_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2);
- void st7735s_spi_draw_point(uint16_t x, uint16_t y, st7735s_spi_color_t color);
- void st7735s_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7735s_spi_color_t color);
- void st7735s_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7735s_spi_color_t *picture);
- void st7735s_spi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7735s_spi_color_t *picture);
- int st7735s_spi_draw_is_busy(void);
- #endif
- #endif
复制代码 st7735s_spi.c
- /**
- * @file st7735s_spi.c
- * @brief
- *
- * Copyright (c) 2021 Bouffalolab team
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- */
- #include "../lcd.h"
- #if defined(LCD_SPI_ST7735S)
- #if (LCD_SPI_INTERFACE_TYPE == 1)
- #include "bl_spi_hard_4.h"
- #define lcd_spi_init lcd_spi_hard_4_init
- #define lcd_spi_isbusy lcd_spi_hard_4_is_busy
- #define lcd_spi_transmit_cmd_para lcd_spi_hard_4_transmit_cmd_para
- #define lcd_spi_transmit_cmd_pixel_sync lcd_spi_hard_4_transmit_cmd_pixel_sync
- #define lcd_spi_transmit_cmd_pixel_fill_sync lcd_spi_hard_4_transmit_cmd_pixel_fill_sync
- #define lcd_spi_sync_callback_enable lcd_spi_hard_4_async_callback_enable
- #define lcd_spi_async_callback_register lcd_spi_hard_4_async_callback_register
- #define lcd_spi_transmit_cmd_pixel_async lcd_spi_hard_4_transmit_cmd_pixel_async
- #define lcd_spi_transmit_cmd_pixel_fill_async lcd_spi_hard_4_transmit_cmd_pixel_fill_async
- static lcd_spi_hard_4_init_t spi_para = {
- .clock_freq = 40 * 1000 * 1000,
- #if (ST7735S_SPI_PIXEL_FORMAT == 1)
- .pixel_format = LCD_SPI_LCD_PIXEL_FORMAT_RGB565,
- #elif (ST7735S_SPI_PIXEL_FORMAT == 2)
- .pixel_format = LCD_SPI_LCD_PIXEL_FORMAT_NRGB8888,
- #endif
- };
- #else
- #error "Configuration error"
- #endif
- const st7735s_spi_init_cmd_t st7735s_spi_init_cmds[] = {
- { 0x11, NULL, 0},
- { 0xFF, NULL, 120 },
- { 0xB1, "\x02\x35\x36", 3 }, //Frame rate 80Hz
- { 0xB2, "\x02\x35\x36", 3 }, //Frame rate 80Hz
- { 0xB3, "\x02\x35\x36\x02\x35\x36", 6 },
- { 0xB4, "\x03", 1 },
- { 0xC0, "\xA2\x02\x84", 3 },
- { 0xC1, "\xC5", 1 },
- { 0xC2, "\x0D\x00", 2},
- { 0xC3, "\x8D\x2A", 2},
- { 0xC4, "\x8D\xEE", 2},
- { 0xC5, "\x0A", 1},
- { 0x36, "\xC8", 1},
- { 0xE0, "\x12\x1C\x10\x18\x33\x2C\x25\x28\x28\x27\x2F\x3c\x00\x03\x03\x10", 16},
- { 0xE1, "\x12\x1C\x10\x18\x2D\x28\x23\x28\x28\x26\x2F\x3B\x00\x03\x03\x10", 16},
- { 0x3A, "\x05", 1}, //65k mode
- { 0x29, NULL, 0 }, //Display on
- };
- /**
- * @brief st7735s_spi_async_callback_enable
- *
- * @return
- */
- void st7735s_spi_async_callback_enable(bool enable)
- {
- lcd_spi_sync_callback_enable(enable);
- }
- /**
- * @brief st7735s_spi_async_callback_register
- *
- * @return
- */
- void st7735s_spi_async_callback_register(void (*callback)(void))
- {
- lcd_spi_async_callback_register(callback);
- }
- /**
- * @brief st7735s_spi_draw_is_busy, After the call st7735s_spi_draw_picture_dma must check this,
- * if st7735s_spi_draw_is_busy() == 1, Don't allow other draw !!
- * can run in the DMA interrupt callback function.
- *
- * @return int 0:draw end; 1:Being draw
- */
- int st7735s_spi_draw_is_busy(void)
- {
- return lcd_spi_isbusy();
- }
- /**
- * @brief st7735s_spi_init
- *
- * @return int
- */
- int st7735s_spi_init()
- {
- lcd_spi_init(&spi_para);
- for (uint16_t i = 0; i < (sizeof(st7735s_spi_init_cmds) / sizeof(st7735s_spi_init_cmds[0])); i++) {
- if (st7735s_spi_init_cmds[i].cmd == 0xFF && st7735s_spi_init_cmds[i].data == NULL && st7735s_spi_init_cmds[i].databytes) {
- bflb_mtimer_delay_ms(st7735s_spi_init_cmds[i].databytes);
- } else {
- lcd_spi_transmit_cmd_para(st7735s_spi_init_cmds[i].cmd, (void *)(st7735s_spi_init_cmds[i].data), st7735s_spi_init_cmds[i].databytes);
- }
- }
- return 0;
- }
- /**
- * @brief
- *
- * @param dir
- * @param mir_flag
- */
- int st7735s_spi_set_dir(uint8_t dir, uint8_t mir_flag)
- {
- uint8_t param;
- switch (dir) {
- case 0:
- if (!mir_flag)
- param = 0x00;
- else
- param = 0x40;
- break;
- case 1:
- if (!mir_flag)
- param = 0x20;
- else
- param = 0xA0;
- break;
- case 2:
- if (!mir_flag)
- param = 0x80;
- else
- param = 0xC0;
- break;
- case 3:
- if (!mir_flag)
- param = 0xE0;
- else
- param = 0x60;
- break;
- default:
- return -1;
- break;
- }
- lcd_spi_transmit_cmd_para(0x36, (void *)¶m, 1);
- return dir;
- }
- /**
- * @brief st7735s_spi_set_draw_window
- *
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- */
- void st7735s_spi_set_draw_window(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
- {
- #if ST7735S_SPI_OFFSET_X
- x1 += ST7735S_SPI_OFFSET_X;
- x2 += ST7735S_SPI_OFFSET_X;
- #endif
- #if ST7735S_SPI_OFFSET_Y
- y1 += ST7735S_SPI_OFFSET_Y;
- y2 += ST7735S_SPI_OFFSET_Y;
- #endif
- int8_t param[4];
- param[0] = (x1 >> 8) & 0xFF;
- param[1] = x1 & 0xFF;
- param[2] = (x2 >> 8) & 0xFF;
- param[3] = x2 & 0xFF;
- lcd_spi_transmit_cmd_para(0x2A, (void *)param, 4);
- param[0] = (y1 >> 8) & 0xFF;
- param[1] = y1 & 0xFF;
- param[2] = (y2 >> 8) & 0xFF;
- param[3] = y2 & 0xFF;
- lcd_spi_transmit_cmd_para(0x2B, (void *)param, 4);
- }
- /**
- * @brief st7735s_spi_draw_point
- *
- * @param x
- * @param y
- * @param color
- */
- void st7735s_spi_draw_point(uint16_t x, uint16_t y, st7735s_spi_color_t color)
- {
- /* set window */
- st7735s_spi_set_draw_window(x, y, x, y);
- lcd_spi_transmit_cmd_pixel_sync(0x2C, (void *)&color, 1);
- }
- /**
- * @brief st7735s_draw_area
- *
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- * @param color
- */
- void st7735s_spi_draw_area(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7735s_spi_color_t color)
- {
- uint32_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
- /* set window */
- st7735s_spi_set_draw_window(x1, y1, x2, y2);
- lcd_spi_transmit_cmd_pixel_fill_sync(0x2C, (uint32_t)color, pixel_cnt);
- }
- /**
- * @brief st7735s_draw_picture_dma, Non-blocking! Using DMA acceleration, Not waiting for the draw end
- * After the call, No other operations are allowed until (st7735s_draw_is_busy()==0)
- *
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- * @param picture
- */
- void st7735s_spi_draw_picture_nonblocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7735s_spi_color_t *picture)
- {
- size_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
- /* set window */
- st7735s_spi_set_draw_window(x1, y1, x2, y2);
- lcd_spi_transmit_cmd_pixel_async(0x2C, (void *)picture, pixel_cnt);
- }
- /**
- * @brief st7735s_draw_picture,Blocking,Using DMA acceleration,Waiting for the draw end
- *
- * @param x1
- * @param y1
- * @param x2
- * @param y2
- * @param picture
- */
- void st7735s_spi_draw_picture_blocking(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, st7735s_spi_color_t *picture)
- {
- size_t pixel_cnt = (x2 - x1 + 1) * (y2 - y1 + 1);
- /* set window */
- st7735s_spi_set_draw_window(x1, y1, x2, y2);
- lcd_spi_transmit_cmd_pixel_sync(0x2C, (void *)picture, pixel_cnt);
- }
- #endif
复制代码 aithinker_Ai-M6X_SDK\bsp\common\lcd\lcd.h中指定位置增加:
- #elif defined LCD_SPI_ST7735S
- #include "spi/st7735s_spi.h"
- #define LCD_INTERFACE_TYPE LCD_INTERFACE_SPI
- #define LCD_W ST7735S_SPI_W
- #define LCD_H ST7735S_SPI_H
- #define LCD_COLOR_DEPTH ST7735S_SPI_COLOR_DEPTH
- #define _LCD_FUNC_DEFINE(_func, ...) st7735s_spi_##_func(__VA_ARGS__)
复制代码
二、说明
1、proj.conf需做如下修改,启用SDK中的LCD模块
set(CONFIG_COMPONENT1 1)
set(CONFIG_BSP_LCD 1)
2、CMakeLists.txt,要加入
sdk_add_include_directories(.)
target_sources(app PRIVATE hzk.c)
编译时可以包含当前目录的.h,编译项目根目录的hzk.c
cmake_minimum_required(VERSION 3.15)
include(proj.conf)
find_package(bouffalo_sdk REQUIRED HINTS $ENV{BL_SDK_BASE})
sdk_add_include_directories(.)
target_sources(app PRIVATE hzk.c)
sdk_set_main_file(main.c)
project(gpio_input_output)
3、main.c 文件需要用VScode中报文为GB2312编码的文件。否则汉字部分无法正确显示。
4、aithinker_Ai-M6X_SDK\bsp\common\CMakeLists.txt
新增:
target_sources(app PRIVATE lcd/spi/st7735s_spi.c)
保证st7735s_spi.c被编译。
5、共享下工程链接:
链接:https://pan.baidu.com/s/1V27W_s3Zb1U4dRiKxlLvyw?pwd=xgez
提取码:xgez
6、接线
|