Ai-M61-32SU+字库+LCD

Ai-M61-32SU 有4M flash,可以下载一个200多K的GB2312_80字库

ed4dcecb0aa44b2c8458e59f63585e7e.png3713c084b9db4fb7b4a5e4c4e1433655.jpg

一、将gb2312_80.bin(字库文件)烧录到Ai-M61-32SU中

1、将gb2312_80.bin放到工程的根目录

1440c9d39f3c4da782a21929773cc8f0.png

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、烧录

make flash COMX=COM10

这样就可以把gb2312_80.bin烧录到0x378000c40f1e10661c4d5f93c36f8882c837e3.png

二、 用于LCD显示及字库读取的程序

main.c

#include "bflb_gpio.h"
#include "bflb_uart.h"

#include "board.h"

#include "lcd.h"
#include "hzk.h"

//#define FLASH_RW_START_ADDR  0x378000
struct bflb_device_s *uartx;
struct bflb_device_s *gpio;
//static uint8_t read_buf[32];

//extern void GUI_Write16CnCharMatrix(unsigned char x, unsigned char y, uint8_t *cn, unsigned short wordColor, unsigned short backColor);

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)
{
    // uint32_t i,j;
    // uint32_t flash_addr;

    board_init();
    board_uartx_gpio_init();
    uart_init();
    lcd_init();


    lcd_clear(LCD_COLOR_RGB565(255,0,0));
    //lcd_draw_str_ascii16(10,10,LCD_COLOR_RGB565(255,255,255),LCD_COLOR_RGB565(255,0,0),(uint8_t*)"hello world!",12);

    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);

    // for (uint32_t offset = 0; offset < 10*sizeof(read_buf); offset+=sizeof(read_buf)){
    //     flash_addr=FLASH_RW_START_ADDR+offset;
    //     memset(read_buf, 0, sizeof(read_buf));
    //     /* read flash data */
    //     bflb_flash_read(flash_addr, read_buf, sizeof(read_buf));
    //     for (j = 0; j < sizeof(read_buf); j++) {
    //         printf("0x%02X,",read_buf[j]);
    //      }
    //       printf("\r\n");
    // }
    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 *)&param, 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

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__)

在lcd_conf.h指定位置增加:

/* spi st7735s config */
#elif defined LCD_SPI_ST7735S

    /* Selecting interface type, more configuration of peripherals comes later
        1: SPI peripheral, supported functions: spi-4wire,
    */
#define LCD_SPI_INTERFACE_TYPE 1

    /* Selecting pixel format
        1: rgb565
    */
#define ST7735S_SPI_PIXEL_FORMAT 1

    /* enable the lcd reset function
        0: Does not care about lcd hard reset
        1: use gpio to reset the lcd
    */
#define LCD_RESET_EN 1

    /* LCD width and height */
#define ST7735S_SPI_W 132
#define ST7735S_SPI_H 132

/* The offset of the area can be displayed */
#define ST7735S_SPI_OFFSET_X 0
#define ST7735S_SPI_OFFSET_Y 0

 lcd_conf.h中有LCD SPI定义:

#define LCD_SPI_HARD_4_PIN_CLK   GPIO_PIN_13
#define LCD_SPI_HARD_4_PIN_DAT   GPIO_PIN_15
/* cs/dc pin, software controlled */
#define LCD_SPI_HARD_4_PIN_CS   GPIO_PIN_14
#define LCD_SPI_HARD_4_PIN_DC   GPIO_PIN_16
#define LCD_RESET_PIN GPIO_PIN_12

三、总结

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 文件需要用记事本保存为ASCII编码文件,或VScode中报文为GB2312编码的文件。否则汉字部分无法正确显示。

  • 17
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值