chrisrh

  • 2024-06-03
  • 回复了主题帖: 新疆的天太好看了!

    江布拉克?

  • 2024-03-18
  • 回复了主题帖: 【ST NUCLEO-U5A5ZJ-Q开发板测评】8、简单的功耗测试

    freebsder 发表于 2024-3-18 17:25 stop和standby之后,还有哪些外设可以监听吗? stop模式有3种,RAM都保持着电,不同stop下保留的外设不同。比如stop2模式下ADC4、SPI3、IIC3都还保持着; 但standby模式下就把所有的外设都掉电了,SWD也进不去,只有RST、BOR, RTC, TAMP, IWDG和24 I/Os (WKUPx)可以唤醒;

  • 回复了主题帖: 【ST NUCLEO-U5A5ZJ-Q开发板测评】7、HASH硬件加速器

    lugl4313820 发表于 2024-3-18 22:30 呀这功能我还没有试过列,好象我目前的工作中还没有这样的需求,所以就少去关注。 比如对上位机通信传输数据的时候可以加密输出,上位机解码;或是上位机加密发给下位机,防止数据被抓吧~

  • 发表了主题帖: 【ST NUCLEO-U5A5ZJ-Q开发板测评】8、简单的功耗测试

    Ultra-low-power with FlexPowerControl • 150 nA Shutdown mode (24 wake-up pins) • 195 nA Standby mode (24 wake-up pins) • 480 nA Standby mode with RTC • 2 μA Stop 3 mode with 40-Kbyte SRAM • 8.2 μA Stop 3 mode with 2.5-Mbyte SRAM • 4.65 µA Stop 2 mode with 40-Kbyte SRAM • 17.5 µA Stop 2 mode with 2.5-Mbyte SRAM • 18.5 μA/MHz Run mode at 3.3 V   将万用表调制电流档,接在板子的IDD处,分别测试了正常RUN模式、Sleep模式、Stop模式、Standby模式下的电流情况 //BSP_LED_Init(LED1); //HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI); //HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI); //HAL_PWR_EnterSTANDBYMode();   160Mhz运行模式下LED1闪烁测量的电流值为7.62mA:   切换至sleep模式测量的电流值为:4.18mA;   切换至stop模式测量的电流值为:1.5uA;   切换至standby模式测量的电流值为:0.6uA;      

  • 发表了主题帖: 【ST NUCLEO-U5A5ZJ-Q开发板测评】7、HASH硬件加速器

    本帖最后由 chrisrh 于 2024-3-18 13:50 编辑 基于U575的demo例程使用了一下U5A5的硬件HASH,响应速度很快; 官方demo使用的是HMAC-MD5 和 SHA1,全称为“Hash Message Authentication Code”,中文名“散列消息鉴别码”,主要是利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。MD5 和 SHA1 就是这种散列函数。HMAC 还可以使用一个用于计算和确认消息鉴别值的密钥。   DEMO原文数据和秘钥数据如下:54686520686173682070726f636573736f7220697320612066756c6c7920636f6d706c69616e7420696d706c656d656e746174696f6e206f662074686520736563757265206861736820616c676f726974686d20285348412d31292c20746865204d443520286d6573736167652d64696765737420616c676f726974686d203529206861736820616c676f726974686d20616e642074686520484d414320286b657965642d68617368206d6573736167652061757468656e7469636174696f6e20636f64652920616c676f726974686d207375697461626c6520666f7220612076617269657479206f66206170706c69636174696f6e732e2a2a2a2053544d3332202a2a2a   在https://www.toolhelper.cn/DigestAlgorithm/HMAC_SHA网页上进行校验计算HMAC-MD5 和 SHA1与demo中比较的数据相一致。 字符编码:Hex(16进制,不编码) 校验:2B47EF34F66658BE3B2AC6EC5885F21ED59FDDAD                     更改输入数据为0x12,0x34,共两个字节,其中HMAC-MD5 为407D8BBD08B21E9D51FDD5EB1300858F   HMAC-SHA1为A588AA7142F6A108B22A89589D9C462B9CC89C8C  更改工程中的原文数据,秘钥还使用原demo中的261个字节数据,编译下载程序,初始化后硬件hash计算的HMAC-MD5 、SHA1如果与预设的结果一致,LED1、LED2灯点亮。 //输入数据的大小 #define INPUT_TAB_SIZE ((uint32_t) 2)//61)/* The size of the input data "aInput" */ HASH_HandleTypeDef hhash; //秘钥 __ALIGN_BEGIN static const uint8_t pKeyHASH[261] __ALIGN_END = {0x54,0x68,0x65,0x20,0x68,0x61,0x73,0x68,0x20,0x70,0x72,0x6f,0x63,0x65,0x73,0x73,0x6f,0x72,0x20,0x69,0x73,0x20,0x61,0x20,0x66,0x75,0x6c,0x6c,0x79,0x20,0x63,0x6f,0x6d,0x70,0x6c,0x69,0x61,0x6e,0x74,0x20,0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x65,0x63,0x75,0x72,0x65,0x20,0x68,0x61,0x73,0x68,0x20,0x61,0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x28,0x53,0x48,0x41,0x2d,0x31,0x29,0x2c,0x20,0x74,0x68,0x65,0x20,0x4d,0x44,0x35,0x20,0x28,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x2d,0x64,0x69,0x67,0x65,0x73,0x74,0x20,0x61,0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x35,0x29,0x20,0x68,0x61,0x73,0x68,0x20,0x61,0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x48,0x4d,0x41,0x43,0x20,0x28,0x6b,0x65,0x79,0x65,0x64,0x2d,0x68,0x61,0x73,0x68,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,0x65,0x20,0x61,0x75,0x74,0x68,0x65,0x6e,0x74,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x20,0x63,0x6f,0x64,0x65,0x29,0x20,0x61,0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x73,0x75,0x69,0x74,0x61,0x62,0x6c,0x65,0x20,0x66,0x6f,0x72,0x20,0x61,0x20,0x76,0x61,0x72,0x69,0x65,0x74,0x79,0x20,0x6f,0x66,0x20,0x61,0x70,0x70,0x6c,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x73,0x2e,0x2a,0x2a,0x2a,0x20,0x53,0x54,0x4d,0x33,0x32,0x20,0x2a,0x2a,0x2a}; //输入的数据 __ALIGN_BEGIN const uint8_t aInput[INPUT_TAB_SIZE] __ALIGN_END = {0x12,0x34}; __ALIGN_BEGIN static uint8_t aMD5Digest[16] __ALIGN_END; __ALIGN_BEGIN static uint8_t aExpectMD5Digest[16] __ALIGN_END = {0x40,0x7D,0x8B, 0xBD, 0x08, 0xB2, 0x1E, 0x9D, 0x51, 0xFD, 0xD5, 0xEB, 0x13, 0x00, 0x85, 0x8F}; __ALIGN_BEGIN static uint8_t aSHA1Digest[20] __ALIGN_END; __ALIGN_BEGIN static uint8_t aExpectSHA1Digest[20] __ALIGN_END = {0xA5,0x88,0xAA,0x71,0x42,0xF6,0xA1,0x08,0xB2,0x2A,0x89,0x58,0x9D,0x9C,0x46,0x2B,0x9C,0xC8,0x9C,0x8C}; static void MX_HASH_Init(void); int main(void) { ... MX_HASH_Init(); if (HAL_HMAC_SHA1_Start(&hhash, (uint8_t *)aInput, INPUT_TAB_SIZE, aSHA1Digest, 0xFF) != HAL_OK) { Error_Handler(); } if (memcmp(aSHA1Digest, aExpectSHA1Digest, sizeof(aExpectSHA1Digest) / sizeof(aExpectSHA1Digest[0])) != 0) { Error_Handler(); } else { BSP_LED_On(LED1); } if(HAL_HASH_DeInit(&hhash) != HAL_OK) { Error_Handler(); } MX_HASH_Init(); /* Compute HMAC-MD5 */ if (HAL_HMAC_MD5_Start(&hhash, (uint8_t *)aInput, INPUT_TAB_SIZE, aMD5Digest, 0xFF) != HAL_OK) { Error_Handler(); } /* Compare computed digest with expected one */ if (memcmp(aMD5Digest, aExpectMD5Digest, sizeof(aExpectMD5Digest) / sizeof(aExpectMD5Digest[0])) != 0) { Error_Handler(); } else {BSP_LED_On(LED2);} while (1) {}   程序运行,LED1、LED2随即点亮,硬件HASH速度很快,解析与预设一致;    

  • 2024-03-15
  • 加入了学习《泰克MSO6B探索营》,观看 MSO6B强大的测试和分析功能

  • 加入了学习《泰克MSO6B探索营》,观看 MSO6B多通道同步频谱分析

  • 加入了学习《泰克MSO6B探索营》,观看 如何完成AI芯片电源噪声测试

  • 加入了学习《泰克MSO6B探索营》,观看 MSO6B系列低噪声演示

  • 加入了学习《泰克MSO6B探索营》,观看 MSO6B技术介绍

  • 加入了学习《泰克MSO6B探索营》,观看 MSO6B-360度介绍

  • 2024-03-14
  • 点评了资料: 嵌入式系统导论CPS方法(中文版)

  • 2024-03-11
  • 回复了主题帖: 【ST NUCLEO-U5A5ZJ-Q开发板测评】6、简单的移植一个GuiLite

    freebsder 发表于 2024-3-11 19:29 GuiLite 这个库是新出来的?以前没听说过呢 应该有两年多了吧,较轻量和全平台,就一个GuiLite.h头文件,确实是大道至简的存在~ Processor Disk/ROM space Memory 24 MHZ 29 KB 9 KB

  • 发表了主题帖: 【ST NUCLEO-U5A5ZJ-Q开发板测评】6、简单的移植一个GuiLite

    本帖最后由 chrisrh 于 2024-3-11 16:22 编辑 基于SPI驱动的LCD,简单的移植GuiLite使用       生成工程,添加LCD驱动代码 main.h 在main.h中添加LCD_IO的宏定义 #define LCD_BL_SET HAL_GPIO_WritePin(LCD_BL_GPIO_Port, LCD_BL_Pin, GPIO_PIN_SET)//BL #define LCD_CS_SET HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET)//CS #define LCD_RS_SET HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET) //RS #define LCD_RST_SET HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_SET)//RST #define LCD_BL_CLR HAL_GPIO_WritePin(LCD_BL_GPIO_Port, LCD_BL_Pin, GPIO_PIN_RESET)//BL #define LCD_CS_CLR HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET)//CS #define LCD_RS_CLR HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET)//RS #define LCD_RST_CLR HAL_GPIO_WritePin(LCD_RST_GPIO_Port, LCD_RST_Pin, GPIO_PIN_RESET)//RST lcd.h LCD的头文件lcd.h,之前偷懒把gui和test都扔这里面了,程序太多了,这次删去··· #ifndef __LCD_H #define __LCD_H #include "stdlib.h" #include "stm32u5xx_hal.h" //LCD重要参数集 typedef struct { uint16_t width; //LCD 宽度 uint16_t height; //LCD 高度 uint16_t id; //LCD ID uint8_t dir; //横屏还是竖屏控制:0,竖屏;1,横屏。 uint16_t wramcmd; //开始写gram指令 uint16_t setxcmd; //设置x坐标指令 uint16_t setycmd; //设置y坐标指令 uint8_t xoffset; uint8_t yoffset; }_lcd_dev; //LCD参数 extern _lcd_dev lcddev; //管理LCD重要参数 /////////////////////////////////////用户配置区/////////////////////////////////// #define USE_HORIZONTAL 0 //定义液晶屏顺时针旋转方向 0-0度旋转,1-90度旋转,2-180度旋转,3-270度旋转 ////////////////////////////////////////////////////////////////////////////////// //定义LCD的尺寸 #define LCD_W 240 #define LCD_H 320 //TFTLCD部分外要调用的函数 extern uint16_t POINT_COLOR;//默认红色 extern uint16_t BACK_COLOR; //背景颜色,默认为白色 /*-----------------LCD端口控制定义----------------*/ //QDtech全系列模块采用了三极管控制背光亮灭,用户也可以接PWM调节背光亮度 //直接操作寄存器可以提高LCD刷屏速率 //画笔颜色 #define WHITE 0xFFFF #define BLACK 0x0000 #define BLUE 0x001F #define BRED 0XF81F #define GRED 0XFFE0 #define GBLUE 0X07FF #define RED 0xF800 #define MAGENTA 0xF81F #define GREEN 0x07E0 #define CYAN 0x7FFF #define YELLOW 0xFFE0 #define BROWN 0XBC40 //棕色 #define BRRED 0XFC07 //棕红色 #define GRAY 0X8430 //灰色 #define GRAY0 0xEF7D #define GRAY1 0x8410 //灰色1 00000 000000 00000 #define GRAY2 0x4208 //GUI颜色 #define DARKBLUE 0X01CF //深蓝色 #define LIGHTBLUE 0X7D7C //浅蓝色 #define GRAYBLUE 0X5458 //灰蓝色 //以上三色为PANEL的颜色 #define LIGHTGREEN 0X841F //浅绿色 #define LIGHTGRAY 0XEF5B //浅灰色(PANNEL) #define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色 #define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色) #define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色) /*----------SPI引脚控制----------------*/ void SPI_WriteByte(uint8_t Data); void LCD_Init(void); void LCD_DisplayOn(void); void LCD_DisplayOff(void); void LCD_Clear(uint16_t Color); void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos); void LCD_DrawPoint(uint16_t x,uint16_t y);//画点 void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); void LCD_SetWindows(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t yEnd); void LCD_WriteReg(uint8_t LCD_Reg, uint16_t LCD_RegValue); void LCD_WR_DATA(uint8_t data); void LCD_WriteRAM_Prepare(void); void LCD_WriteRAM(uint16_t RGB_Code); uint16_t LCD_ReadRAM(void); uint16_t LCD_BGR2RGB(uint16_t c); void LCD_SetParam(void); void LCD_WriteData_16Bit(uint16_t Data); void LCD_direction(uint8_t direction); ////////////////////////////////////////////////////////////////// /*GUI*/ ////////////////////////////////////////////////////////////////// void GUI_DrawPoint(uint16_t x,uint16_t y,uint16_t color); void LCD_Fill(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey,uint16_t color); void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); void Draw_Triangel(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2); void Fill_Triangel(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2); void Draw_Circle(uint16_t x0,uint16_t y0,uint16_t fc,uint8_t r); void gui_circle(int32_t xc, int32_t yc,uint16_t c,int32_t r, int32_t fill); #endif lcd.c 添加lcd.c #include "lcd.h" #include "stdlib.h" #include "string.h" #include "main.h" //#include "pic.h" //#include "font.h" //管理LCD重要参数 //默认为竖屏 _lcd_dev lcddev; //画笔颜色,背景颜色 uint16_t POINT_COLOR = 0x0000,BACK_COLOR = 0xFFFF; uint16_t DeviceCode; uint16_t ColorTab[5]={RED,GREEN,BLUE,YELLOW,BRED}; extern SPI_HandleTypeDef hspi1; /***************************************************************************** * [url=home.php?mod=space&uid=32621]@name[/url] :void LCD_WR_REG(u8 data) * [url=home.php?mod=space&uid=311857]@date[/url] :2018-08-09 * [url=home.php?mod=space&uid=665173]@FUNCTION[/url] :Write an 8-bit command to the LCD screen * @parameters :data:Command value to be written * @retvalue :None ******************************************************************************/ void LCD_WR_REG(uint8_t data) { LCD_CS_CLR; LCD_RS_CLR; SPI_WriteByte(data); LCD_CS_SET; } /***************************************************************************** * @name :void LCD_WR_DATA(u8 data) * @date :2018-08-09 * @function :Write an 8-bit data to the LCD screen * @parameters :data:data value to be written * @retvalue :None ******************************************************************************/ void LCD_WR_DATA(uint8_t data) { LCD_CS_CLR; LCD_RS_SET; SPI_WriteByte(data); LCD_CS_SET; } /***************************************************************************** * @name :void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue) * @date :2018-08-09 * @function :Write data into registers * @parameters :LCD_Reg:Register address LCD_RegValue:Data to be written * @retvalue :None ******************************************************************************/ void LCD_WriteReg(uint8_t LCD_Reg, uint16_t LCD_RegValue) { LCD_WR_REG(LCD_Reg); LCD_WR_DATA(LCD_RegValue); } /***************************************************************************** * @name :void LCD_WriteRAM_Prepare(void) * @date :2018-08-09 * @function :Write GRAM * @parameters :None * @retvalue :None ******************************************************************************/ void LCD_WriteRAM_Prepare(void) { LCD_WR_REG(lcddev.wramcmd); } /***************************************************************************** * @name :void Lcd_WriteData_16Bit(u16 Data) * @date :2018-08-09 * @function :Write an 16-bit command to the LCD screen * @parameters :Data:Data to be written * @retvalue :None ******************************************************************************/ void LCD_WriteData_16Bit(uint16_t Data) { LCD_CS_CLR; LCD_RS_SET; SPI_WriteByte(Data>>8); SPI_WriteByte(Data); LCD_CS_SET; } /***************************************************************************** * @name :void LCD_DrawPoint(u16 x,u16 y) * @date :2018-08-09 * @function :Write a pixel data at a specified location * @parameters :x:the x coordinate of the pixel y:the y coordinate of the pixel * @retvalue :None ******************************************************************************/ void LCD_DrawPoint(uint16_t x,uint16_t y) { LCD_SetCursor(x,y);//设置光标位置 LCD_WriteData_16Bit(POINT_COLOR); } /***************************************************************************** * @name :void LCD_Clear(u16 Color) * @date :2018-08-09 * @function :Full screen filled LCD screen * @parameters :color:Filled color * @retvalue :None ******************************************************************************/ void LCD_Clear(uint16_t Color) { uint32_t i,m; LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1); LCD_CS_CLR; LCD_RS_SET; for(i=0;i<lcddev.height;i++) { for(m=0;m<lcddev.width;m++) { SPI_WriteByte(Color>>8); SPI_WriteByte(Color); } } LCD_CS_SET; } /***************************************************************************** * @name :void LCD_GPIOInit(void) * @date :2018-08-09 * @function :Initialization LCD screen GPIO * @parameters :None * @retvalue :None ******************************************************************************/ void LCD_GPIOInit(void) { // GPIO_InitTypeDef GPIO_InitStructure; // __HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIOB时钟 // // GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; //高速 // GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出 // GPIO_InitStructure.Pull = GPIO_PULLUP; //上拉 // // GPIO_InitStructure.Pin = LCD_BL_PIN; // HAL_GPIO_Init(LCD_BL_PORT, &GPIO_InitStructure);//初始化BL引脚 // // GPIO_InitStructure.Pin = LCD_CS_PIN; // HAL_GPIO_Init(LCD_CS_PORT, &GPIO_InitStructure);//初始化CS引脚 // // GPIO_InitStructure.Pin = LCD_RS_PIN; // HAL_GPIO_Init(LCD_RS_PORT, &GPIO_InitStructure);//初始化RS引脚 // // GPIO_InitStructure.Pin = LCD_RST_PIN; // HAL_GPIO_Init(LCD_RST_PORT, &GPIO_InitStructure);//初始化RST引脚 // //默认所有的引脚都拉高 LCD_BL_SET; LCD_CS_SET; LCD_RS_SET; LCD_RST_SET; } /***************************************************************************** * @name :void LCD_RESET(void) * @date :2018-08-09 * @function :Reset LCD screen * @parameters :None * @retvalue :None ******************************************************************************/ void LCD_RESET(void) { LCD_RST_CLR; HAL_Delay(20); LCD_RST_SET; HAL_Delay(20); } /***************************************************************************** * @name :void LCD_RESET(void) * @date :2018-08-09 * @function :Initialization LCD screen * @parameters :None * @retvalue :None ******************************************************************************/ void LCD_Init(void) { // SPI_GPIO_Init(); //硬件SPI1初始化 // SPI_SCLK_SET; // SPI_MOSI_SET; LCD_GPIOInit();//LCD GPIO初始化 LCD_RESET(); //LCD 复位 //************* ST7789 IPS初始化**********// LCD_WR_REG(0x36); LCD_WR_DATA(0x00); LCD_WR_REG(0x3A); LCD_WR_DATA(0x05); LCD_WR_REG(0xB2); LCD_WR_DATA(0x0C); LCD_WR_DATA(0x0C); LCD_WR_DATA(0x00); LCD_WR_DATA(0x33); LCD_WR_DATA(0x33); LCD_WR_REG(0xB7); LCD_WR_DATA(0x35); LCD_WR_REG(0xBB); LCD_WR_DATA(0x17); LCD_WR_REG(0xC0); LCD_WR_DATA(0x2C); LCD_WR_REG(0xC2); LCD_WR_DATA(0x01); LCD_WR_REG(0xC3); LCD_WR_DATA(0x12); LCD_WR_REG(0xC4); LCD_WR_DATA(0x20); LCD_WR_REG(0xC6); LCD_WR_DATA(0x0F); LCD_WR_REG(0xD0); LCD_WR_DATA(0xA4); LCD_WR_DATA(0xA1); LCD_WR_REG(0xE0); LCD_WR_DATA(0xD0); LCD_WR_DATA(0x04); LCD_WR_DATA(0x0D); LCD_WR_DATA(0x11); LCD_WR_DATA(0x13); LCD_WR_DATA(0x2B); LCD_WR_DATA(0x3F); LCD_WR_DATA(0x54); LCD_WR_DATA(0x4C); LCD_WR_DATA(0x18); LCD_WR_DATA(0x0D); LCD_WR_DATA(0x0B); LCD_WR_DATA(0x1F); LCD_WR_DATA(0x23); LCD_WR_REG(0xE1); LCD_WR_DATA(0xD0); LCD_WR_DATA(0x04); LCD_WR_DATA(0x0C); LCD_WR_DATA(0x11); LCD_WR_DATA(0x13); LCD_WR_DATA(0x2C); LCD_WR_DATA(0x3F); LCD_WR_DATA(0x44); LCD_WR_DATA(0x51); LCD_WR_DATA(0x2F); LCD_WR_DATA(0x1F); LCD_WR_DATA(0x1F); LCD_WR_DATA(0x20); LCD_WR_DATA(0x23); LCD_WR_REG(0x21); LCD_WR_REG(0x11); //Delay (120); LCD_WR_REG(0x29); LCD_direction(USE_HORIZONTAL);//设置LCD显示方向 LCD_BL_SET;//点亮背光 LCD_Clear(WHITE);//清全屏白色 } /***************************************************************************** * @name :void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd) * @date :2018-08-09 * @function :Setting LCD display window * @parameters :xStar:the bebinning x coordinate of the LCD display window yStar:the bebinning y coordinate of the LCD display window xEnd:the endning x coordinate of the LCD display window yEnd:the endning y coordinate of the LCD display window * @retvalue :None ******************************************************************************/ void LCD_SetWindows(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t yEnd) { LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA((xStar+lcddev.xoffset)>>8); LCD_WR_DATA(xStar+lcddev.xoffset); LCD_WR_DATA((xEnd+lcddev.xoffset)>>8); LCD_WR_DATA(xEnd+lcddev.xoffset); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA((yStar+lcddev.yoffset)>>8); LCD_WR_DATA(yStar+lcddev.yoffset); LCD_WR_DATA((yEnd+lcddev.yoffset)>>8); LCD_WR_DATA(yEnd+lcddev.yoffset); LCD_WriteRAM_Prepare(); //开始写入GRAM } /***************************************************************************** * @name :void LCD_SetCursor(u16 Xpos, u16 Ypos) * @date :2018-08-09 * @function :Set coordinate value * @parameters :Xpos:the x coordinate of the pixel Ypos:the y coordinate of the pixel * @retvalue :None ******************************************************************************/ void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos) { LCD_SetWindows(Xpos,Ypos,Xpos,Ypos); } /***************************************************************************** * @name :void LCD_direction(u8 direction) * @date :2018-08-09 * @function :Setting the display direction of LCD screen * @parameters :direction:0-0 degree 1-90 degree 2-180 degree 3-270 degree * @retvalue :None ******************************************************************************/ void LCD_direction(uint8_t direction) { lcddev.setxcmd=0x2A; lcddev.setycmd=0x2B; lcddev.wramcmd=0x2C; lcddev.dir = direction%4; switch(lcddev.dir){ case 0: lcddev.width=LCD_W; lcddev.height=LCD_H; lcddev.xoffset=0; lcddev.yoffset=0; LCD_WriteReg(0x36,0);//BGR==1,MY==0,MX==0,MV==0 break; case 1: lcddev.width=LCD_H; lcddev.height=LCD_W; lcddev.xoffset=0; lcddev.yoffset=0; LCD_WriteReg(0x36,(1<<6)|(1<<5));//BGR==1,MY==1,MX==0,MV==1 break; case 2: lcddev.width=LCD_W; lcddev.height=LCD_H; lcddev.xoffset=0; lcddev.yoffset=122; LCD_WriteReg(0x36,(1<<6)|(1<<7));//BGR==1,MY==0,MX==0,MV==0 break; case 3: lcddev.width=LCD_H; lcddev.height=LCD_W; lcddev.xoffset=122; lcddev.yoffset=0; LCD_WriteReg(0x36,(1<<7)|(1<<5));//BGR==1,MY==1,MX==0,MV==1 break; default:break; } } /***************************************************************************** * @name :void SPI_WriteByte(u8 Data) * @date :2018-08-09 * @function :Write a byte of data using STM32's Software SPI * @parameters :Data:Data to be written * @retvalue :None ******************************************************************************/ //void SPI_WriteByte(uint8_t Data) //{ // uint8_t i=0; // for(i=8;i>0;i--) // { // if(Data&0x80) // SPI_MOSI_SET; //输出数据 // else // SPI_MOSI_CLR; // SPI_SCLK_CLR; // SPI_SCLK_SET; // Data<<=1; // } //} void SPI_WriteByte(uint8_t Data) { HAL_SPI_Transmit(&hspi1,&Data,1,1); // HAL_Delay(10); } ////////////////////////////////////////////////////////////////// /*GUI*/ ////////////////////////////////////////////////////////////////// /******************************************************************* * @name :void GUI_DrawPoint(u16 x,u16 y,u16 color) * @date :2018-08-09 * @function :draw a point in LCD screen * @parameters :x:the x coordinate of the point y:the y coordinate of the point color:the color value of the point * @retvalue :None ********************************************************************/ void GUI_DrawPoint(uint16_t x,uint16_t y,uint16_t color) { LCD_SetCursor(x,y);//设置光标位置 LCD_WriteData_16Bit(color); } /******************************************************************* * @name :void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color) * @date :2018-08-09 * @function :fill the specified area * @parameters :sx:the bebinning x coordinate of the specified area sy:the bebinning y coordinate of the specified area ex:the ending x coordinate of the specified area ey:the ending y coordinate of the specified area color:the filled color value * @retvalue :None ********************************************************************/ void LCD_Fill(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey,uint16_t color) { uint16_t i,j; uint16_t width=ex-sx+1; //得到填充的宽度 uint16_t height=ey-sy+1; //高度 LCD_SetWindows(sx,sy,ex,ey);//设置显示窗口 for(i=0;i<height;i++) { for(j=0;j<width;j++) LCD_WriteData_16Bit(color); //写入数据 } LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口设置为全屏 } /******************************************************************* * @name :void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2) * @date :2018-08-09 * @function :Draw a line between two points * @parameters :x1:the bebinning x coordinate of the line y1:the bebinning y coordinate of the line x2:the ending x coordinate of the line y2:the ending y coordinate of the line * @retvalue :None ********************************************************************/ void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { uint16_t t; int32_t xerr=0,yerr=0,delta_x,delta_y,distance; int32_t incx,incy,uRow,uCol; delta_x=x2-x1; //计算坐标增量 delta_y=y2-y1; uRow=x1; uCol=y1; if(delta_x>0)incx=1; //设置单步方向 else if(delta_x==0)incx=0;//垂直线 else {incx=-1;delta_x=-delta_x;} if(delta_y>0)incy=1; else if(delta_y==0)incy=0;//水平线 else{incy=-1;delta_y=-delta_y;} if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 else distance=delta_y; for(t=0;t<=distance+1;t++ )//画线输出 { LCD_DrawPoint(uRow,uCol);//画点 xerr+=delta_x ; yerr+=delta_y ; if(xerr>distance) { xerr-=distance; uRow+=incx; } if(yerr>distance) { yerr-=distance; uCol+=incy; } } } /***************************************************************************** * @name :void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2) * @date :2018-08-09 * @function :Draw a rectangle * @parameters :x1:the bebinning x coordinate of the rectangle y1:the bebinning y coordinate of the rectangle x2:the ending x coordinate of the rectangle y2:the ending y coordinate of the rectangle * @retvalue :None ******************************************************************************/ void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { LCD_DrawLine(x1,y1,x2,y1); LCD_DrawLine(x1,y1,x1,y2); LCD_DrawLine(x1,y2,x2,y2); LCD_DrawLine(x2,y1,x2,y2); } /***************************************************************************** * @name :void Draw_Triangel(u16 x0,u16 y0,u16 x1,u16 y1,u16 x2,u16 y2) * @date :2018-08-09 * @function :Draw a triangle at a specified position * @parameters :x0:the bebinning x coordinate of the triangular edge y0:the bebinning y coordinate of the triangular edge x1:the vertex x coordinate of the triangular y1:the vertex y coordinate of the triangular x2:the ending x coordinate of the triangular edge y2:the ending y coordinate of the triangular edge * @retvalue :None ******************************************************************************/ void Draw_Triangel(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2) { LCD_DrawLine(x0,y0,x1,y1); LCD_DrawLine(x1,y1,x2,y2); LCD_DrawLine(x2,y2,x0,y0); } static void _swap(uint16_t *a, uint16_t *b) { uint16_t tmp; tmp = *a; *a = *b; *b = tmp; } /***************************************************************************** * @name :void Fill_Triangel(u16 x0,u16 y0,u16 x1,u16 y1,u16 x2,u16 y2) * @date :2018-08-09 * @function :filling a triangle at a specified position * @parameters :x0:the bebinning x coordinate of the triangular edge y0:the bebinning y coordinate of the triangular edge x1:the vertex x coordinate of the triangular y1:the vertex y coordinate of the triangular x2:the ending x coordinate of the triangular edge y2:the ending y coordinate of the triangular edge * @retvalue :None ******************************************************************************/ void Fill_Triangel(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2) { uint16_t a, b, y, last; int dx01, dy01, dx02, dy02, dx12, dy12; long sa = 0; long sb = 0; if (y0 > y1) { _swap(&y0,&y1); _swap(&x0,&x1); } if (y1 > y2) { _swap(&y2,&y1); _swap(&x2,&x1); } if (y0 > y1) { _swap(&y0,&y1); _swap(&x0,&x1); } if(y0 == y2) { a = b = x0; if(x1 < a) { a = x1; } else if(x1 > b) { b = x1; } if(x2 < a) { a = x2; } else if(x2 > b) { b = x2; } LCD_Fill(a,y0,b,y0,POINT_COLOR); return; } dx01 = x1 - x0; dy01 = y1 - y0; dx02 = x2 - x0; dy02 = y2 - y0; dx12 = x2 - x1; dy12 = y2 - y1; if(y1 == y2) { last = y1; } else { last = y1-1; } for(y=y0; y<=last; y++) { a = x0 + sa / dy01; b = x0 + sb / dy02; sa += dx01; sb += dx02; if(a > b) { _swap(&a,&b); } LCD_Fill(a,y,b,y,POINT_COLOR); } sa = dx12 * (y - y1); sb = dx02 * (y - y0); for(; y<=y2; y++) { a = x1 + sa / dy12; b = x0 + sb / dy02; sa += dx12; sb += dx02; if(a > b) { _swap(&a,&b); } LCD_Fill(a,y,b,y,POINT_COLOR); } } /***************************************************************************** * @name :void _draw_circle_8(int xc, int yc, int x, int y, u16 c) * @date :2018-08-09 * @function :8 symmetry circle drawing algorithm (internal call) * @parameters :xc:the x coordinate of the Circular center yc:the y coordinate of the Circular center x:the x coordinate relative to the Circular center y:the y coordinate relative to the Circular center c:the color value of the circle * @retvalue :None ******************************************************************************/ void _draw_circle_8(int32_t xc, int32_t yc, int32_t x, int32_t y, uint16_t c) { GUI_DrawPoint(xc + x, yc + y, c); GUI_DrawPoint(xc - x, yc + y, c); GUI_DrawPoint(xc + x, yc - y, c); GUI_DrawPoint(xc - x, yc - y, c); GUI_DrawPoint(xc + y, yc + x, c); GUI_DrawPoint(xc - y, yc + x, c); GUI_DrawPoint(xc + y, yc - x, c); GUI_DrawPoint(xc - y, yc - x, c); } /***************************************************************************** * @name :void gui_circle(int xc, int yc,u16 c,int r, int fill) * @date :2018-08-09 * @function :Draw a circle of specified size at a specified location * @parameters :xc:the x coordinate of the Circular center yc:the y coordinate of the Circular center r:Circular radius fill:1-filling,0-no filling * @retvalue :None ******************************************************************************/ void gui_circle(int32_t xc, int32_t yc,uint16_t c,int32_t r, int32_t fill) { int32_t x = 0, y = r, yi, d; d = 3 - 2 * r; if (fill) { // 如果填充(画实心圆) while (x <= y) { for (yi = x; yi <= y; yi++) _draw_circle_8(xc, yc, x, yi, c); if (d < 0) { d = d + 4 * x + 6; } else { d = d + 4 * (x - y) + 10; y--; } x++; } } else { // 如果不填充(画空心圆) while (x <= y) { _draw_circle_8(xc, yc, x, y, c); if (d < 0) { d = d + 4 * x + 6; } else { d = d + 4 * (x - y) + 10; y--; } x++; } } }   移植GuiLite idea4good (idea4good) - Gitee.com ①、下载GuiLiteSamples,进入待移植的项目,找到UIcode;   ②、将需要移植的UIcode添加到工程中,添加UIcode.cpp和GuiLite.h到工程中   ③、确认画点函数,GUI_DrawPoint(uint16_t x,uint16_t y,uint16_t color); 然后在main.c中main函数前添加 void delay_ms(int ms) { HAL_Delay(ms); } //RGB888/RGB565 //Transfer GuiLite 32 bits color to your LCD color #define GL_RGB_32_to_16(rgb) (((((unsigned int)(rgb)) & 0xFF) >> 3) | ((((unsigned int)(rgb)) & 0xFC00) >> 5) | ((((unsigned int)(rgb)) & 0xF80000) >> 8)) //Encapsulate your LCD driver: void gfx_draw_pixel(int x, int y, unsigned int rgb) { GUI_DrawPoint(x, y, GL_RGB_32_to_16(rgb)); } //Implement it, if you have more fast solution than drawing pixels one by one. //void gfx_fill_rect(int x0, int y0, int x1, int y1, unsigned int rgb){} //UI entry struct EXTERNAL_GFX_OP { void (*draw_pixel)(int x, int y, unsigned int rgb); void (*fill_rect)(int x0, int y0, int x1, int y1, unsigned int rgb); } my_gfx_op; extern void startHello3D(void* phy_fb, int width, int height, int color_bytes, struct EXTERNAL_GFX_OP* gfx_op); ④、在while(1)前添加启动函数 LCD_Init(); my_gfx_op.draw_pixel = gfx_draw_pixel; my_gfx_op.fill_rect = NULL;//gfx_fill_rect; startHello3D(NULL, 240, 320, 2, &my_gfx_op); 运行并下载工程即可; [localvideo]f58cd9c9b18039e9bd5fc615f739189c[/localvideo] [localvideo]93a64536b0e32024b864e3a3a5c8f84a[/localvideo] 没有开SPI_DMA,没有用硬件加速,单SPI驱动,比之前在L452Nucleo上SPI+DMA的响应要快很多,一方面可能是因为系统和spi的主频增加了,另一方面可能是U5的架构吧。后续试下SPI_DMA驱动的效果。  

  • 2024-03-09
  • 点评了资料: Keil.STM32U5xx_DFP.2.1.0

  • 发表了主题帖: 【ST NUCLEO-U5A5ZJ-Q开发板测评】5、SPI和LCD

    本帖最后由 chrisrh 于 2024-3-9 09:47 编辑 SPI和LCD LCD用的是个7789的2.4寸LCD,自己之前画的底板,适配插焊用的18PIN接口屏幕,TB上的电阻触摸屏;   屏幕的驱动,在www.lcdwiki.com查找7789更改使用的,先点亮屏幕,再跟进自己的需求进行更改 使用STM32cubeMX基于U5A5-nucleo板生成基础工程,在工程内开启SPI,选用SPI1 引脚如下: PA5<->SPI1_SCK PA7<->SPI1_MOSI PA6<->LCD_CS PB8<->LCD_RST PB9<->LCD_DC PF12<->LCD_BL         主时钟是160Mhz,时钟里SPI也是160Mhz,在配置SPI1分频的时候选择4分频,分配到40Mhz才能正常使用SPI;   生成工程,在工程中添加lcd.c、lcd.h、font.h lcd.c如下 #include "lcd.h" #include "stdlib.h" #include "string.h" #include "main.h" #include "pic.h" #include "font.h" //管理LCD重要参数 //默认为竖屏 _lcd_dev lcddev; //画笔颜色,背景颜色 uint16_t POINT_COLOR = 0x0000,BACK_COLOR = 0xFFFF; uint16_t DeviceCode; uint16_t ColorTab[5]={RED,GREEN,BLUE,YELLOW,BRED}; extern SPI_HandleTypeDef hspi1; /***************************************************************************** * @name :void LCD_WR_REG(u8 data) * @date :2018-08-09 * @FUNCTION :Write an 8-bit command to the LCD screen * @parameters :data:Command value to be written * @retvalue :None ******************************************************************************/ void LCD_WR_REG(uint8_t data) { LCD_CS_CLR; LCD_RS_CLR; SPI_WriteByte(data); LCD_CS_SET; } /***************************************************************************** * @name :void LCD_WR_DATA(u8 data) * @date :2018-08-09 * @function :Write an 8-bit data to the LCD screen * @parameters :data:data value to be written * @retvalue :None ******************************************************************************/ void LCD_WR_DATA(uint8_t data) { LCD_CS_CLR; LCD_RS_SET; SPI_WriteByte(data); LCD_CS_SET; } /***************************************************************************** * @name :void LCD_WriteReg(u8 LCD_Reg, u16 LCD_RegValue) * @date :2018-08-09 * @function :Write data into registers * @parameters :LCD_Reg:Register address LCD_RegValue:Data to be written * @retvalue :None ******************************************************************************/ void LCD_WriteReg(uint8_t LCD_Reg, uint16_t LCD_RegValue) { LCD_WR_REG(LCD_Reg); LCD_WR_DATA(LCD_RegValue); } /***************************************************************************** * @name :void LCD_WriteRAM_Prepare(void) * @date :2018-08-09 * @function :Write GRAM * @parameters :None * @retvalue :None ******************************************************************************/ void LCD_WriteRAM_Prepare(void) { LCD_WR_REG(lcddev.wramcmd); } /***************************************************************************** * @name :void Lcd_WriteData_16Bit(u16 Data) * @date :2018-08-09 * @function :Write an 16-bit command to the LCD screen * @parameters :Data:Data to be written * @retvalue :None ******************************************************************************/ void LCD_WriteData_16Bit(uint16_t Data) { LCD_CS_CLR; LCD_RS_SET; SPI_WriteByte(Data>>8); SPI_WriteByte(Data); LCD_CS_SET; } /***************************************************************************** * @name :void LCD_DrawPoint(u16 x,u16 y) * @date :2018-08-09 * @function :Write a pixel data at a specified location * @parameters :x:the x coordinate of the pixel y:the y coordinate of the pixel * @retvalue :None ******************************************************************************/ void LCD_DrawPoint(uint16_t x,uint16_t y) { LCD_SetCursor(x,y);//设置光标位置 LCD_WriteData_16Bit(POINT_COLOR); } /***************************************************************************** * @name :void LCD_Clear(u16 Color) * @date :2018-08-09 * @function :Full screen filled LCD screen * @parameters :color:Filled color * @retvalue :None ******************************************************************************/ void LCD_Clear(uint16_t Color) { uint32_t i,m; LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1); LCD_CS_CLR; LCD_RS_SET; for(i=0;i<lcddev.height;i++) { for(m=0;m<lcddev.width;m++) { SPI_WriteByte(Color>>8); SPI_WriteByte(Color); } } LCD_CS_SET; } /***************************************************************************** * @name :void LCD_GPIOInit(void) * @date :2018-08-09 * @function :Initialization LCD screen GPIO * @parameters :None * @retvalue :None ******************************************************************************/ void LCD_GPIOInit(void) { // GPIO_InitTypeDef GPIO_InitStructure; // __HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIOB时钟 // // GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH; //高速 // GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出 // GPIO_InitStructure.Pull = GPIO_PULLUP; //上拉 // // GPIO_InitStructure.Pin = LCD_BL_PIN; // HAL_GPIO_Init(LCD_BL_PORT, &GPIO_InitStructure);//初始化BL引脚 // // GPIO_InitStructure.Pin = LCD_CS_PIN; // HAL_GPIO_Init(LCD_CS_PORT, &GPIO_InitStructure);//初始化CS引脚 // // GPIO_InitStructure.Pin = LCD_RS_PIN; // HAL_GPIO_Init(LCD_RS_PORT, &GPIO_InitStructure);//初始化RS引脚 // // GPIO_InitStructure.Pin = LCD_RST_PIN; // HAL_GPIO_Init(LCD_RST_PORT, &GPIO_InitStructure);//初始化RST引脚 // //默认所有的引脚都拉高 LCD_BL_SET; LCD_CS_SET; LCD_RS_SET; LCD_RST_SET; } /***************************************************************************** * @name :void LCD_RESET(void) * @date :2018-08-09 * @function :Reset LCD screen * @parameters :None * @retvalue :None ******************************************************************************/ void LCD_RESET(void) { LCD_RST_CLR; HAL_Delay(20); LCD_RST_SET; HAL_Delay(20); } /***************************************************************************** * @name :void LCD_RESET(void) * @date :2018-08-09 * @function :Initialization LCD screen * @parameters :None * @retvalue :None ******************************************************************************/ void LCD_Init(void) { //SPI_GPIO_Init(); //硬件SPI1初始化 // SPI_SCLK_SET; // SPI_MOSI_SET; LCD_GPIOInit();//LCD GPIO初始化 LCD_RESET(); //LCD 复位 //************* ST7789 IPS初始化**********// LCD_WR_REG(0x36); LCD_WR_DATA(0x00); LCD_WR_REG(0x3A); LCD_WR_DATA(0x05); LCD_WR_REG(0xB2); LCD_WR_DATA(0x0C); LCD_WR_DATA(0x0C); LCD_WR_DATA(0x00); LCD_WR_DATA(0x33); LCD_WR_DATA(0x33); LCD_WR_REG(0xB7); LCD_WR_DATA(0x35); LCD_WR_REG(0xBB); LCD_WR_DATA(0x17); LCD_WR_REG(0xC0); LCD_WR_DATA(0x2C); LCD_WR_REG(0xC2); LCD_WR_DATA(0x01); LCD_WR_REG(0xC3); LCD_WR_DATA(0x12); LCD_WR_REG(0xC4); LCD_WR_DATA(0x20); LCD_WR_REG(0xC6); LCD_WR_DATA(0x0F); LCD_WR_REG(0xD0); LCD_WR_DATA(0xA4); LCD_WR_DATA(0xA1); LCD_WR_REG(0xE0); LCD_WR_DATA(0xD0); LCD_WR_DATA(0x04); LCD_WR_DATA(0x0D); LCD_WR_DATA(0x11); LCD_WR_DATA(0x13); LCD_WR_DATA(0x2B); LCD_WR_DATA(0x3F); LCD_WR_DATA(0x54); LCD_WR_DATA(0x4C); LCD_WR_DATA(0x18); LCD_WR_DATA(0x0D); LCD_WR_DATA(0x0B); LCD_WR_DATA(0x1F); LCD_WR_DATA(0x23); LCD_WR_REG(0xE1); LCD_WR_DATA(0xD0); LCD_WR_DATA(0x04); LCD_WR_DATA(0x0C); LCD_WR_DATA(0x11); LCD_WR_DATA(0x13); LCD_WR_DATA(0x2C); LCD_WR_DATA(0x3F); LCD_WR_DATA(0x44); LCD_WR_DATA(0x51); LCD_WR_DATA(0x2F); LCD_WR_DATA(0x1F); LCD_WR_DATA(0x1F); LCD_WR_DATA(0x20); LCD_WR_DATA(0x23); LCD_WR_REG(0x21); LCD_WR_REG(0x11); //Delay (120); LCD_WR_REG(0x29); LCD_direction(USE_HORIZONTAL);//设置LCD显示方向 LCD_BL_SET;//点亮背光 LCD_Clear(WHITE);//清全屏白色 } /***************************************************************************** * @name :void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd) * @date :2018-08-09 * @function :Setting LCD display window * @parameters :xStar:the bebinning x coordinate of the LCD display window yStar:the bebinning y coordinate of the LCD display window xEnd:the endning x coordinate of the LCD display window yEnd:the endning y coordinate of the LCD display window * @retvalue :None ******************************************************************************/ void LCD_SetWindows(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t yEnd) { LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA((xStar+lcddev.xoffset)>>8); LCD_WR_DATA(xStar+lcddev.xoffset); LCD_WR_DATA((xEnd+lcddev.xoffset)>>8); LCD_WR_DATA(xEnd+lcddev.xoffset); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA((yStar+lcddev.yoffset)>>8); LCD_WR_DATA(yStar+lcddev.yoffset); LCD_WR_DATA((yEnd+lcddev.yoffset)>>8); LCD_WR_DATA(yEnd+lcddev.yoffset); LCD_WriteRAM_Prepare(); //开始写入GRAM } /***************************************************************************** * @name :void LCD_SetCursor(u16 Xpos, u16 Ypos) * @date :2018-08-09 * @function :Set coordinate value * @parameters :Xpos:the x coordinate of the pixel Ypos:the y coordinate of the pixel * @retvalue :None ******************************************************************************/ void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos) { LCD_SetWindows(Xpos,Ypos,Xpos,Ypos); } /***************************************************************************** * @name :void LCD_direction(u8 direction) * @date :2018-08-09 * @function :Setting the display direction of LCD screen * @parameters :direction:0-0 degree 1-90 degree 2-180 degree 3-270 degree * @retvalue :None ******************************************************************************/ void LCD_direction(uint8_t direction) { lcddev.setxcmd=0x2A; lcddev.setycmd=0x2B; lcddev.wramcmd=0x2C; lcddev.dir = direction%4; switch(lcddev.dir){ case 0: lcddev.width=LCD_W; lcddev.height=LCD_H; lcddev.xoffset=0; lcddev.yoffset=0; LCD_WriteReg(0x36,0);//BGR==1,MY==0,MX==0,MV==0 break; case 1: lcddev.width=LCD_H; lcddev.height=LCD_W; lcddev.xoffset=0; lcddev.yoffset=0; LCD_WriteReg(0x36,(1<<6)|(1<<5));//BGR==1,MY==1,MX==0,MV==1 break; case 2: lcddev.width=LCD_W; lcddev.height=LCD_H; lcddev.xoffset=0; lcddev.yoffset=122; LCD_WriteReg(0x36,(1<<6)|(1<<7));//BGR==1,MY==0,MX==0,MV==0 break; case 3: lcddev.width=LCD_H; lcddev.height=LCD_W; lcddev.xoffset=122; lcddev.yoffset=0; LCD_WriteReg(0x36,(1<<7)|(1<<5));//BGR==1,MY==1,MX==0,MV==1 break; default:break; } } /***************************************************************************** * @name :void SPI_WriteByte(u8 Data) * @date :2018-08-09 * @function :Write a byte of data using STM32's Software SPI * @parameters :Data:Data to be written * @retvalue :None ******************************************************************************/ //void SPI_WriteByte(uint8_t Data) //{ // uint8_t i=0; // for(i=8;i>0;i--) // { // if(Data&0x80) // SPI_MOSI_SET; //输出数据 // else // SPI_MOSI_CLR; // SPI_SCLK_CLR; // SPI_SCLK_SET; // Data<<=1; // } //} void SPI_WriteByte(uint8_t Data) { HAL_SPI_Transmit(&hspi1,&Data,1,1); // HAL_Delay(10); } ////////////////////////////////////////////////////////////////// /*GUI*/ ////////////////////////////////////////////////////////////////// /******************************************************************* * @name :void GUI_DrawPoint(u16 x,u16 y,u16 color) * @date :2018-08-09 * @function :draw a point in LCD screen * @parameters :x:the x coordinate of the point y:the y coordinate of the point color:the color value of the point * @retvalue :None ********************************************************************/ void GUI_DrawPoint(uint16_t x,uint16_t y,uint16_t color) { LCD_SetCursor(x,y);//设置光标位置 LCD_WriteData_16Bit(color); } /******************************************************************* * @name :void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color) * @date :2018-08-09 * @function :fill the specified area * @parameters :sx:the bebinning x coordinate of the specified area sy:the bebinning y coordinate of the specified area ex:the ending x coordinate of the specified area ey:the ending y coordinate of the specified area color:the filled color value * @retvalue :None ********************************************************************/ void LCD_Fill(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey,uint16_t color) { uint16_t i,j; uint16_t width=ex-sx+1; //得到填充的宽度 uint16_t height=ey-sy+1; //高度 LCD_SetWindows(sx,sy,ex,ey);//设置显示窗口 for(i=0;i<height;i++) { for(j=0;j<width;j++) LCD_WriteData_16Bit(color); //写入数据 } LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口设置为全屏 } /******************************************************************* * @name :void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2) * @date :2018-08-09 * @function :Draw a line between two points * @parameters :x1:the bebinning x coordinate of the line y1:the bebinning y coordinate of the line x2:the ending x coordinate of the line y2:the ending y coordinate of the line * @retvalue :None ********************************************************************/ void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { uint16_t t; int32_t xerr=0,yerr=0,delta_x,delta_y,distance; int32_t incx,incy,uRow,uCol; delta_x=x2-x1; //计算坐标增量 delta_y=y2-y1; uRow=x1; uCol=y1; if(delta_x>0)incx=1; //设置单步方向 else if(delta_x==0)incx=0;//垂直线 else {incx=-1;delta_x=-delta_x;} if(delta_y>0)incy=1; else if(delta_y==0)incy=0;//水平线 else{incy=-1;delta_y=-delta_y;} if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 else distance=delta_y; for(t=0;t<=distance+1;t++ )//画线输出 { LCD_DrawPoint(uRow,uCol);//画点 xerr+=delta_x ; yerr+=delta_y ; if(xerr>distance) { xerr-=distance; uRow+=incx; } if(yerr>distance) { yerr-=distance; uCol+=incy; } } } /***************************************************************************** * @name :void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2) * @date :2018-08-09 * @function :Draw a rectangle * @parameters :x1:the bebinning x coordinate of the rectangle y1:the bebinning y coordinate of the rectangle x2:the ending x coordinate of the rectangle y2:the ending y coordinate of the rectangle * @retvalue :None ******************************************************************************/ void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { LCD_DrawLine(x1,y1,x2,y1); LCD_DrawLine(x1,y1,x1,y2); LCD_DrawLine(x1,y2,x2,y2); LCD_DrawLine(x2,y1,x2,y2); } /***************************************************************************** * @name :void LCD_DrawFillRectangle(u16 x1, u16 y1, u16 x2, u16 y2) * @date :2018-08-09 * @function :Filled a rectangle * @parameters :x1:the bebinning x coordinate of the filled rectangle y1:the bebinning y coordinate of the filled rectangle x2:the ending x coordinate of the filled rectangle y2:the ending y coordinate of the filled rectangle * @retvalue :None ******************************************************************************/ void LCD_DrawFillRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) { LCD_Fill(x1,y1,x2,y2,POINT_COLOR); } /***************************************************************************** * @name :void Draw_Triangel(u16 x0,u16 y0,u16 x1,u16 y1,u16 x2,u16 y2) * @date :2018-08-09 * @function :Draw a triangle at a specified position * @parameters :x0:the bebinning x coordinate of the triangular edge y0:the bebinning y coordinate of the triangular edge x1:the vertex x coordinate of the triangular y1:the vertex y coordinate of the triangular x2:the ending x coordinate of the triangular edge y2:the ending y coordinate of the triangular edge * @retvalue :None ******************************************************************************/ void Draw_Triangel(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2) { LCD_DrawLine(x0,y0,x1,y1); LCD_DrawLine(x1,y1,x2,y2); LCD_DrawLine(x2,y2,x0,y0); } static void _swap(uint16_t *a, uint16_t *b) { uint16_t tmp; tmp = *a; *a = *b; *b = tmp; } /***************************************************************************** * @name :void Fill_Triangel(u16 x0,u16 y0,u16 x1,u16 y1,u16 x2,u16 y2) * @date :2018-08-09 * @function :filling a triangle at a specified position * @parameters :x0:the bebinning x coordinate of the triangular edge y0:the bebinning y coordinate of the triangular edge x1:the vertex x coordinate of the triangular y1:the vertex y coordinate of the triangular x2:the ending x coordinate of the triangular edge y2:the ending y coordinate of the triangular edge * @retvalue :None ******************************************************************************/ void Fill_Triangel(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2) { uint16_t a, b, y, last; int dx01, dy01, dx02, dy02, dx12, dy12; long sa = 0; long sb = 0; if (y0 > y1) { _swap(&y0,&y1); _swap(&x0,&x1); } if (y1 > y2) { _swap(&y2,&y1); _swap(&x2,&x1); } if (y0 > y1) { _swap(&y0,&y1); _swap(&x0,&x1); } if(y0 == y2) { a = b = x0; if(x1 < a) { a = x1; } else if(x1 > b) { b = x1; } if(x2 < a) { a = x2; } else if(x2 > b) { b = x2; } LCD_Fill(a,y0,b,y0,POINT_COLOR); return; } dx01 = x1 - x0; dy01 = y1 - y0; dx02 = x2 - x0; dy02 = y2 - y0; dx12 = x2 - x1; dy12 = y2 - y1; if(y1 == y2) { last = y1; } else { last = y1-1; } for(y=y0; y<=last; y++) { a = x0 + sa / dy01; b = x0 + sb / dy02; sa += dx01; sb += dx02; if(a > b) { _swap(&a,&b); } LCD_Fill(a,y,b,y,POINT_COLOR); } sa = dx12 * (y - y1); sb = dx02 * (y - y0); for(; y<=y2; y++) { a = x1 + sa / dy12; b = x0 + sb / dy02; sa += dx12; sb += dx02; if(a > b) { _swap(&a,&b); } LCD_Fill(a,y,b,y,POINT_COLOR); } } /***************************************************************************** * @name :void _draw_circle_8(int xc, int yc, int x, int y, u16 c) * @date :2018-08-09 * @function :8 symmetry circle drawing algorithm (internal call) * @parameters :xc:the x coordinate of the Circular center yc:the y coordinate of the Circular center x:the x coordinate relative to the Circular center y:the y coordinate relative to the Circular center c:the color value of the circle * @retvalue :None ******************************************************************************/ void _draw_circle_8(int32_t xc, int32_t yc, int32_t x, int32_t y, uint16_t c) { GUI_DrawPoint(xc + x, yc + y, c); GUI_DrawPoint(xc - x, yc + y, c); GUI_DrawPoint(xc + x, yc - y, c); GUI_DrawPoint(xc - x, yc - y, c); GUI_DrawPoint(xc + y, yc + x, c); GUI_DrawPoint(xc - y, yc + x, c); GUI_DrawPoint(xc + y, yc - x, c); GUI_DrawPoint(xc - y, yc - x, c); } /***************************************************************************** * @name :void gui_circle(int xc, int yc,u16 c,int r, int fill) * @date :2018-08-09 * @function :Draw a circle of specified size at a specified location * @parameters :xc:the x coordinate of the Circular center yc:the y coordinate of the Circular center r:Circular radius fill:1-filling,0-no filling * @retvalue :None ******************************************************************************/ void gui_circle(int32_t xc, int32_t yc,uint16_t c,int32_t r, int32_t fill) { int32_t x = 0, y = r, yi, d; d = 3 - 2 * r; if (fill) { // 如果填充(画实心圆) while (x <= y) { for (yi = x; yi <= y; yi++) _draw_circle_8(xc, yc, x, yi, c); if (d < 0) { d = d + 4 * x + 6; } else { d = d + 4 * (x - y) + 10; y--; } x++; } } else { // 如果不填充(画空心圆) while (x <= y) { _draw_circle_8(xc, yc, x, y, c); if (d < 0) { d = d + 4 * x + 6; } else { d = d + 4 * (x - y) + 10; y--; } x++; } } } /***************************************************************************** * @name :void LCD_ShowChar(u16 x,u16 y,u16 fc, u16 bc, u8 num,u8 size,u8 mode) * @date :2018-08-09 * @function :Display a single English character * @parameters :x:the bebinning x coordinate of the Character display position y:the bebinning y coordinate of the Character display position fc:the color value of display character bc:the background color of display character num:the ascii code of display character(0~94) size:the size of display character mode:0-no overlying,1-overlying * @retvalue :None ******************************************************************************/ void LCD_ShowChar(uint16_t x,uint16_t y,uint16_t fc, uint16_t bc, uint8_t num,uint8_t size,uint8_t mode) { uint8_t temp; uint8_t pos,t; uint16_t colortemp=POINT_COLOR; num=num-' ';//得到偏移后的值 if(!mode) //非叠加方式 { LCD_SetWindows(x,y,x+size/2-1,y+size-1);//设置单个文字显示窗口 for(pos=0;pos<size;pos++) { if(size==12)temp=asc2_1206[num][pos];//调用1206字体 else temp=asc2_1608[num][pos]; //调用1608字体 for(t=0;t<size/2;t++) { if(temp&0x01) LCD_WriteData_16Bit(fc); else LCD_WriteData_16Bit(bc); temp>>=1; } } }else//叠加方式 { for(pos=0;pos<size;pos++) { if(size==12)temp=asc2_1206[num][pos];//调用1206字体 else temp=asc2_1608[num][pos]; //调用1608字体 for(t=0;t<size/2;t++) { POINT_COLOR=fc; if(temp&0x01)LCD_DrawPoint(x+t,y+pos);//画一个点 temp>>=1; } } } POINT_COLOR=colortemp; LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口为全屏 } /***************************************************************************** * @name :void LCD_ShowString(u16 x,u16 y,u8 size,u8 *p,u8 mode) * @date :2018-08-09 * @function :Display English string * @parameters :x:the bebinning x coordinate of the English string y:the bebinning y coordinate of the English string p:the start address of the English string size:the size of display character mode:0-no overlying,1-overlying * @retvalue :None ******************************************************************************/ void LCD_ShowString(uint16_t x,uint16_t y,uint8_t size,uint8_t *p,uint8_t mode) { while((*p<='~')&&(*p>=' '))//判断是不是非法字符! { if(x>(lcddev.width-1)||y>(lcddev.height-1)) return; LCD_ShowChar(x,y,POINT_COLOR,BACK_COLOR,*p,size,mode); x+=size/2; p++; } } /***************************************************************************** * @name :u32 mypow(u8 m,u8 n) * @date :2018-08-09 * @function :get the nth power of m (internal call) * @parameters :m:the multiplier n:the power * @retvalue :the nth power of m ******************************************************************************/ uint32_t mypow(uint8_t m,uint8_t n) { uint32_t result=1; while(n--)result*=m; return result; } /***************************************************************************** * @name :void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size) * @date :2018-08-09 * @function :Display number * @parameters :x:the bebinning x coordinate of the number y:the bebinning y coordinate of the number num:the number(0~4294967295) len:the length of the display number size:the size of display number * @retvalue :None ******************************************************************************/ void LCD_ShowNum(uint16_t x,uint16_t y,uint32_t num,uint8_t len,uint8_t size) { uint8_t t,temp; uint8_t enshow=0; for(t=0;t<len;t++) { temp=(num/mypow(10,len-t-1))%10; if(enshow==0&&t<(len-1)) { if(temp==0) { LCD_ShowChar(x+(size/2)*t,y,POINT_COLOR,BACK_COLOR,' ',size,0); continue; }else enshow=1; } LCD_ShowChar(x+(size/2)*t,y,POINT_COLOR,BACK_COLOR,temp+'0',size,0); } } /***************************************************************************** * @name :void GUI_DrawFont16(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode) * @date :2018-08-09 * @function :Display a single 16x16 Chinese character * @parameters :x:the bebinning x coordinate of the Chinese character y:the bebinning y coordinate of the Chinese character fc:the color value of Chinese character bc:the background color of Chinese character s:the start address of the Chinese character mode:0-no overlying,1-overlying * @retvalue :None ******************************************************************************/ void GUI_DrawFont16(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s,uint8_t mode) { uint8_t i,j; uint16_t k; uint16_t HZnum; uint16_t x0=x; HZnum=sizeof(tfont16)/sizeof(typFNT_GB16); //自动统计汉字数目 for (k=0;k<HZnum;k++) { if ((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1))) { if(!mode) { LCD_SetWindows(x,y,x+16-1,y+16-1); for(i=0;i<16*2;i++) { for(j=0;j<8;j++) { if(tfont16[k].Msk[i]&(0x80>>j)) LCD_WriteData_16Bit(fc); else LCD_WriteData_16Bit(bc); } } } else { for(i=0;i<16*2;i++) { for(j=0;j<8;j++) { POINT_COLOR=fc; if(tfont16[k].Msk[i]&(0x80>>j)) LCD_DrawPoint(x,y);//画一个点 x++; if((x-x0)==16) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口为全屏 } /***************************************************************************** * @name :void GUI_DrawFont24(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode) * @date :2018-08-09 * @function :Display a single 24x24 Chinese character * @parameters :x:the bebinning x coordinate of the Chinese character y:the bebinning y coordinate of the Chinese character fc:the color value of Chinese character bc:the background color of Chinese character s:the start address of the Chinese character mode:0-no overlying,1-overlying * @retvalue :None ******************************************************************************/ void GUI_DrawFont24(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s,uint8_t mode) { uint8_t i,j; uint16_t k; uint16_t HZnum; uint16_t x0=x; HZnum=sizeof(tfont24)/sizeof(typFNT_GB24); //自动统计汉字数目 for (k=0;k<HZnum;k++) { if ((tfont24[k].Index[0]==*(s))&&(tfont24[k].Index[1]==*(s+1))) { if(!mode) //非叠加方式 { LCD_SetWindows(x,y,x+24-1,y+24-1); for(i=0;i<24*3;i++) { for(j=0;j<8;j++) { if(tfont24[k].Msk[i]&(0x80>>j)) LCD_WriteData_16Bit(fc); else LCD_WriteData_16Bit(bc); } } } else { for(i=0;i<24*3;i++) { for(j=0;j<8;j++) { POINT_COLOR=fc; if(tfont24[k].Msk[i]&(0x80>>j)) LCD_DrawPoint(x,y);//画一个点 x++; if((x-x0)==24) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口为全屏 } /***************************************************************************** * @name :void GUI_DrawFont32(u16 x, u16 y, u16 fc, u16 bc, u8 *s,u8 mode) * @date :2018-08-09 * @function :Display a single 32x32 Chinese character * @parameters :x:the bebinning x coordinate of the Chinese character y:the bebinning y coordinate of the Chinese character fc:the color value of Chinese character bc:the background color of Chinese character s:the start address of the Chinese character mode:0-no overlying,1-overlying * @retvalue :None ******************************************************************************/ void GUI_DrawFont32(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s,uint8_t mode) { uint8_t i,j; uint16_t k; uint16_t HZnum; uint16_t x0=x; HZnum=sizeof(tfont32)/sizeof(typFNT_GB32); //自动统计汉字数目 for (k=0;k<HZnum;k++) { if ((tfont32[k].Index[0]==*(s))&&(tfont32[k].Index[1]==*(s+1))) { if(!mode) //非叠加方式 { LCD_SetWindows(x,y,x+32-1,y+32-1); for(i=0;i<32*4;i++) { for(j=0;j<8;j++) { if(tfont32[k].Msk[i]&(0x80>>j)) LCD_WriteData_16Bit(fc); else LCD_WriteData_16Bit(bc); } } } else { for(i=0;i<32*4;i++) { for(j=0;j<8;j++) { POINT_COLOR=fc; if(tfont32[k].Msk[i]&(0x80>>j)) LCD_DrawPoint(x,y);//画一个点 x++; if((x-x0)==32) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口为全屏 } /***************************************************************************** * @name :void Show_Str(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode) * @date :2018-08-09 * @function :Display Chinese and English strings * @parameters :x:the bebinning x coordinate of the Chinese and English strings y:the bebinning y coordinate of the Chinese and English strings fc:the color value of Chinese and English strings bc:the background color of Chinese and English strings str:the start address of the Chinese and English strings size:the size of Chinese and English strings mode:0-no overlying,1-overlying * @retvalue :None ******************************************************************************/ void Show_Str(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *str,uint8_t size,uint8_t mode) { uint16_t x0=x; uint8_t bHz=0; //字符或者中文 while(*str!=0)//数据未结束 { if(!bHz) { if(x>(lcddev.width-size/2)||y>(lcddev.height-size)) return; if(*str>0x80)bHz=1;//中文 else //字符 { if(*str==0x0D)//换行符号 { y+=size; x=x0; str++; } else { if(size>16)//字库中没有集成12X24 16X32的英文字体,用8X16代替 { LCD_ShowChar(x,y,fc,bc,*str,16,mode); x+=8; //字符,为全字的一半 } else { LCD_ShowChar(x,y,fc,bc,*str,size,mode); x+=size/2; //字符,为全字的一半 } } str++; } }else//中文 { if(x>(lcddev.width-size)||y>(lcddev.height-size)) return; bHz=0;//有汉字库 if(size==32) GUI_DrawFont32(x,y,fc,bc,str,mode); else if(size==24) GUI_DrawFont24(x,y,fc,bc,str,mode); else GUI_DrawFont16(x,y,fc,bc,str,mode); str+=2; x+=size;//下一个汉字偏移 } } } /***************************************************************************** * @name :void Gui_StrCenter(u16 x, u16 y, u16 fc, u16 bc, u8 *str,u8 size,u8 mode) * @date :2018-08-09 * @function :Centered display of English and Chinese strings * @parameters :x:the bebinning x coordinate of the Chinese and English strings y:the bebinning y coordinate of the Chinese and English strings fc:the color value of Chinese and English strings bc:the background color of Chinese and English strings str:the start address of the Chinese and English strings size:the size of Chinese and English strings mode:0-no overlying,1-overlying * @retvalue :None ******************************************************************************/ void Gui_StrCenter(int16_t x, int16_t y, uint16_t fc, uint16_t bc, uint8_t *str,uint8_t size,uint8_t mode) { uint16_t len=strlen((const char *)str); uint16_t x1=(lcddev.width-len*8)/2; Show_Str(x+x1,y,fc,bc,str,size,mode); } /***************************************************************************** * @name :void Gui_Drawbmp16(u16 x,u16 y,const unsigned char *p) * @date :2018-08-09 * @function :Display a 16-bit BMP image * @parameters :x:the bebinning x coordinate of the BMP image y:the bebinning y coordinate of the BMP image p:the start address of image array * @retvalue :None ******************************************************************************/ void Gui_Drawbmp16(uint16_t x,uint16_t y,uint16_t w, uint16_t h, const unsigned char *p) //显示40*40 QQ图片 { int32_t i; uint8_t picH,picL; LCD_SetWindows(x,y,x+w-1,y+h-1);//窗口设置 for(i=0;i<w*h;i++) { picH=*(p+i*2); //数据低位在前 picL=*(p+i*2+1); LCD_WriteData_16Bit(picH<<8|picL); } LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复显示窗口为全屏 } void Test_Triangle(void) { uint8_t i=0; LCD_Fill(0,30,lcddev.width-1,lcddev.height-32,WHITE); for(i=0;i<5;i++) { POINT_COLOR=ColorTab[i]; Draw_Triangel(lcddev.width/2-40+(i*15),lcddev.height/2-12+(i*11),lcddev.width/2-25-1+(i*15),lcddev.height/2-12-26-1+(i*11),lcddev.width/2-10-1+(i*15),lcddev.height/2-12+(i*11)); } HAL_Delay(1500); LCD_Fill(0,30,lcddev.width-1,lcddev.height-32,WHITE); for(i=0;i<5;i++) { POINT_COLOR=ColorTab[i]; Fill_Triangel(lcddev.width/2-40+(i*15),lcddev.height/2-12+(i*11),lcddev.width/2-25-1+(i*15),lcddev.height/2-12-26-1+(i*11),lcddev.width/2-10-1+(i*15),lcddev.height/2-12+(i*11)); } HAL_Delay(1500); } /***************************************************************************** * @name :void DrawTestPage(u8 *str) * @date :2018-08-09 * @function :Drawing test interface * @parameters :str:the start address of the Chinese and English strings * @retvalue :None ******************************************************************************/ void DrawTestPage(uint8_t *str) { //绘制固定栏up LCD_Clear(WHITE); //LCD_Fill(0,0,lcddev.width,20,BLUE); //绘制固定栏down //LCD_Fill(0,lcddev.height-20,lcddev.width,lcddev.height,BLUE); //POINT_COLOR=BLUE; if(lcddev.dir==0) { LCD_Fill(0,0,lcddev.width-1,28,BLUE); LCD_Fill(0,lcddev.height-16,lcddev.width-1,lcddev.height-1,BLUE); Gui_StrCenter(0,12,WHITE,BLUE,str,16,0);//居中显示 Gui_StrCenter(0,lcddev.height-16,WHITE,BLUE,"www.lcdwiki.com",16,0);//居中显示 } else if(lcddev.dir==2) { LCD_Fill(0,0,lcddev.width-1,16,BLUE); LCD_Fill(0,lcddev.height-30,lcddev.width-1,lcddev.height-1,BLUE); Gui_StrCenter(0,0,WHITE,BLUE,str,16,0);//居中显示 Gui_StrCenter(0,lcddev.height-30,WHITE,BLUE,"www.lcdwiki.com",16,0);//居中显示 } else if(lcddev.dir==1) { LCD_Fill(0,0,lcddev.width-1,28,BLUE); LCD_Fill(0,lcddev.height-32,lcddev.width-1,lcddev.height-1,BLUE); Gui_StrCenter(21,12,WHITE,BLUE,str,16,0);//居中显示 Gui_StrCenter(21,lcddev.height-32,WHITE,BLUE,"www.lcdwiki.com",16,0);//居中显示 } else { LCD_Fill(0,0,lcddev.width-1,28,BLUE); LCD_Fill(0,lcddev.height-32,lcddev.width-1,lcddev.height-1,BLUE); Gui_StrCenter(-21,12,WHITE,BLUE,str,16,0);//居中显示 Gui_StrCenter(-21,lcddev.height-32,WHITE,BLUE,"www.lcdwiki.com",16,0);//居中显示 } //绘制测试区域 //LCD_Fill(0,20,lcddev.width,lcddev.height-20,WHITE); } /***************************************************************************** * @name :void Display_ButtonUp(u16 x1,u16 y1,u16 x2,u16 y2) * @date :2018-08-24 * @function :Drawing a 3D button * @parameters :x1:the bebinning x coordinate of the button y1:the bebinning y coordinate of the button x2:the ending x coordinate of the button y2:the ending y coordinate of the button * @retvalue :None ******************************************************************************/ void Display_ButtonUp(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2) { POINT_COLOR=WHITE; LCD_DrawLine(x1, y1, x2,y1); //H LCD_DrawLine(x1, y1, x1,y2); //V POINT_COLOR=GRAY1; LCD_DrawLine(x1+1,y2-1,x2,y2-1); //H POINT_COLOR=GRAY2; LCD_DrawLine(x1,y2,x2,y2); //H POINT_COLOR=GRAY1; LCD_DrawLine(x2-1,y1+1,x2-1,y2); //V POINT_COLOR=GRAY2; LCD_DrawLine(x2,y1,x2,y2); //V } /***************************************************************************** * @name :void menu_test(void) * @date :2018-08-24 * @function :Drawing a 3D menu UI * @parameters :None * @retvalue :None ******************************************************************************/ void menu_test(void) { LCD_Clear(GRAY0); Display_ButtonUp((lcddev.width-98)/2,65,(lcddev.width-98)/2+98,85); //x1,y1,x2,y2 Gui_StrCenter(0,67,BRED,BLUE,"图形显示测试",16,1); Display_ButtonUp((lcddev.width-98)/2,95,(lcddev.width-98)/2+98,115); //x1,y1,x2,y2 Gui_StrCenter(0,97,BLACK,GRAY0,"纯色填充测试",16,1); Display_ButtonUp((lcddev.width-98)/2,125,(lcddev.width-98)/2+98,145); //x1,y1,x2,y2 Gui_StrCenter(0,127,BLUE,GRAY0,"中文显示测试",16,1); Display_ButtonUp((lcddev.width-98)/2,155,(lcddev.width-98)/2+98,175); //x1,y1,x2,y2 Gui_StrCenter(0,157,RED,GRAY0,"图片显示测试",16,1); HAL_Delay(1500); HAL_Delay(500); } /***************************************************************************** * @name :void main_test(void) * @date :2018-08-09 * @function :Drawing the main Interface of the Comprehensive Test Program * @parameters :None * @retvalue :None ******************************************************************************/ void main_test(void) { DrawTestPage("综合测试程序"); Gui_StrCenter(0,78,RED,BLUE,"电子测试",16,1);//居中显示 Gui_StrCenter(0,95,RED,BLUE,"综合测试程序",16,1);//居中显示 Gui_StrCenter(0,112,GREEN,BLUE,"2.4\" ST7789",16,1);//居中显示 Gui_StrCenter(0,129,GREEN,BLUE,"240X320",16,1);//居中显示 Gui_StrCenter(0,146,BLUE,BLUE,"2024-03-06",16,1);//居中显示 HAL_Delay(1500); HAL_Delay(1500); } /***************************************************************************** * @name :void Test_Color(void) * @date :2018-08-09 * @function :Color fill test(white,black,red,green,blue) * @parameters :None * @retvalue :None ******************************************************************************/ void Test_Color(void) { //DrawTestPage("测试1:纯色填充测试"); LCD_Fill(0,0,lcddev.width-1,lcddev.height-1,WHITE); Show_Str(40,30,BLACK,YELLOW,"WHITE",16,1);HAL_Delay(1000); LCD_Fill(0,0,lcddev.width-1,lcddev.height-1,BLACK); Show_Str(40,30,WHITE,YELLOW,"BLACK",16,1);HAL_Delay(1000); LCD_Fill(0,0,lcddev.width-1,lcddev.height-1,RED); Show_Str(40,30,BLUE,YELLOW,"RED",16,1);HAL_Delay(800); LCD_Fill(0,0,lcddev.width-1,lcddev.height-1,GREEN); Show_Str(40,30,BLUE,YELLOW,"GREEN",16,1);HAL_Delay(800); LCD_Fill(0,0,lcddev.width-1,lcddev.height-1,BLUE); Show_Str(40,30,RED,YELLOW,"BLUE",16,1);HAL_Delay(800); LCD_Fill(0,0,lcddev.width-1,lcddev.height-1,GRAY); Show_Str(40,30,RED,YELLOW,"GRAY",16,1);HAL_Delay(1000); } /***************************************************************************** * @name :void Test_FillRec(void) * @date :2018-08-09 * @function :Rectangular display and fill test Display red,green,blue,yellow,pink rectangular boxes in turn, 1500 milliseconds later, Fill the rectangle in red,green,blue,yellow and pink in turn * @parameters :None * @retvalue :None ******************************************************************************/ void Test_FillRec(void) { uint8_t i=0; DrawTestPage("GUI矩形填充测试"); LCD_Fill(0,30,lcddev.width-1,lcddev.height-32,WHITE); for (i=0; i<5; i++) { POINT_COLOR=ColorTab[i]; LCD_DrawRectangle(lcddev.width/2-40+(i*16),lcddev.height/2-40+(i*13),lcddev.width/2-40+(i*16)+30,lcddev.height/2-40+(i*13)+30); } HAL_Delay(1500); LCD_Fill(0,30,lcddev.width-1,lcddev.height-32,WHITE); for (i=0; i<5; i++) { POINT_COLOR=ColorTab[i]; LCD_DrawFillRectangle(lcddev.width/2-40+(i*16),lcddev.height/2-40+(i*13),lcddev.width/2-40+(i*16)+30,lcddev.height/2-40+(i*13)+30); } HAL_Delay(1500); } /***************************************************************************** * @name :void Test_Circle(void) * @date :2018-08-09 * @function :circular display and fill test Display red,green,blue,yellow,pink circular boxes in turn, 1500 milliseconds later, Fill the circular in red,green,blue,yellow and pink in turn * @parameters :None * @retvalue :None ******************************************************************************/ void Test_Circle(void) { uint8_t i=0; DrawTestPage("GUI画圆填充测试"); LCD_Fill(0,30,lcddev.width-1,lcddev.height-32,WHITE); for (i=0; i<5; i++) gui_circle(lcddev.width/2-40+(i*15),lcddev.height/2-25+(i*13),ColorTab[i],15,0); HAL_Delay(1500); LCD_Fill(0,30,lcddev.width-1,lcddev.height-32,WHITE); for (i=0; i<5; i++) gui_circle(lcddev.width/2-40+(i*15),lcddev.height/2-25+(i*13),ColorTab[i],15,1); HAL_Delay(1500); } /***************************************************************************** * @name :void English_Font_test(void) * @date :2018-08-09 * @function :English display test * @parameters :None * @retvalue :None ******************************************************************************/ void English_Font_test(void) { DrawTestPage("英文显示测试"); Show_Str(50,77,BLUE,YELLOW,"6X12:abcdefgh01234567",12,0); Show_Str(50,89,BLUE,YELLOW,"6X12:ABCDEFGH01234567",12,1); Show_Str(50,101,BLUE,YELLOW,"6X12:~!@#$%^&*()_+{}:",12,0); Show_Str(50,114,BLUE,YELLOW,"8X16:abcde01234",16,0); Show_Str(50,130,BLUE,YELLOW,"8X16:ABCDE01234",16,1); Show_Str(50,146,BLUE,YELLOW,"8X16:~!@#$%^&*()",16,0); HAL_Delay(1200); } /***************************************************************************** * @name :void Chinese_Font_test(void) * @date :2018-08-09 * @function :chinese display test * @parameters :None * @retvalue :None ******************************************************************************/ void Chinese_Font_test(void) { DrawTestPage("中文显示测试"); Show_Str(45,82,BLUE,YELLOW,"16X16:电子测试",16,0); Show_Str(45,102,BLUE,YELLOW,"24X24:中文测试",24,1); Show_Str(45,127,BLUE,YELLOW,"32X32:字体测试",32,1); HAL_Delay(1200); } /***************************************************************************** * @name :void Pic_test(void) * @date :2018-08-09 * @function :picture display test * @parameters :None * @retvalue :None ******************************************************************************/ void Pic_test(void) { DrawTestPage("图片显示测试"); //LCD_Fill(0,20,lcddev.width,lcddev.height-20,WHITE); Gui_Drawbmp16(50,90,40,40,gImage_qq); Show_Str(50+12,135,BLUE,YELLOW,"QQ",16,1); Gui_Drawbmp16(100,90,40,40,gImage_qq); Show_Str(100+12,135,BLUE,YELLOW,"QQ",16,1); Gui_Drawbmp16(150,90,40,40,gImage_qq); Show_Str(150+12,135,BLUE,YELLOW,"QQ",16,1); HAL_Delay(1200); } /***************************************************************************** * @name :void Rotate_Test(void) * @date :2018-08-09 * @function :rotate test * @parameters :None * @retvalue :None ******************************************************************************/ void Rotate_Test(void) { uint8_t i=0; uint8_t *Direction[4]={"Rotation:0","Rotation:90","Rotation:180","Rotation:270"}; for(i=0;i<4;i++) { LCD_direction(i); DrawTestPage("屏幕旋转测试"); Show_Str(40,35,BLUE,YELLOW,Direction[i],16,1); Gui_Drawbmp16(40,55,40,40,gImage_qq); HAL_Delay(1000);HAL_Delay(1000); } LCD_direction(USE_HORIZONTAL); } /***************************************************************************** * @name :void Test_Dynamic_Num(void) * @date :2018-11-13 * @function :Dynamic number test * @parameters :None * @retvalue :None ******************************************************************************/ void Test_Dynamic_Num(void) { uint8_t i; DrawTestPage("动态数字显示"); POINT_COLOR=BLUE; srand(123456); LCD_ShowString(40,100,16,"PM2.5: ug/m3",1); LCD_ShowString(40,120,16," TEP: C",1); POINT_COLOR=RED; for(i=0;i<15;i++) { LCD_ShowNum(90,100,rand()%10000,5,16); LCD_ShowNum(90,120,rand()%50,5,16); HAL_Delay(500); } } lcd.h如下 #ifndef __LCD_H #define __LCD_H #include "stdlib.h" #include "stm32u5xx_hal.h" //LCD重要参数集 typedef struct { uint16_t width; //LCD 宽度 uint16_t height; //LCD 高度 uint16_t id; //LCD ID uint8_t dir; //横屏还是竖屏控制:0,竖屏;1,横屏。 uint16_t wramcmd; //开始写gram指令 uint16_t setxcmd; //设置x坐标指令 uint16_t setycmd; //设置y坐标指令 uint8_t xoffset; uint8_t yoffset; }_lcd_dev; //LCD参数 extern _lcd_dev lcddev; //管理LCD重要参数 /////////////////////////////////////用户配置区/////////////////////////////////// #define USE_HORIZONTAL 0 //定义液晶屏顺时针旋转方向 0-0度旋转,1-90度旋转,2-180度旋转,3-270度旋转 ////////////////////////////////////////////////////////////////////////////////// //定义LCD的尺寸 #define LCD_W 240 #define LCD_H 320 //TFTLCD部分外要调用的函数 extern uint16_t POINT_COLOR;//默认红色 extern uint16_t BACK_COLOR; //背景颜色,默认为白色 /*-----------------LCD端口控制定义----------------*/ //QDtech全系列模块采用了三极管控制背光亮灭,用户也可以接PWM调节背光亮度 //直接操作寄存器可以提高LCD刷屏速率 //画笔颜色 #define WHITE 0xFFFF #define BLACK 0x0000 #define BLUE 0x001F #define BRED 0XF81F #define GRED 0XFFE0 #define GBLUE 0X07FF #define RED 0xF800 #define MAGENTA 0xF81F #define GREEN 0x07E0 #define CYAN 0x7FFF #define YELLOW 0xFFE0 #define BROWN 0XBC40 //棕色 #define BRRED 0XFC07 //棕红色 #define GRAY 0X8430 //灰色 #define GRAY0 0xEF7D #define GRAY1 0x8410 //灰色1 00000 000000 00000 #define GRAY2 0x4208 //GUI颜色 #define DARKBLUE 0X01CF //深蓝色 #define LIGHTBLUE 0X7D7C //浅蓝色 #define GRAYBLUE 0X5458 //灰蓝色 //以上三色为PANEL的颜色 #define LIGHTGREEN 0X841F //浅绿色 #define LIGHTGRAY 0XEF5B //浅灰色(PANNEL) #define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色 #define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色) #define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色) /*----------SPI引脚控制----------------*/ void SPI_WriteByte(uint8_t Data); void LCD_Init(void); void LCD_DisplayOn(void); void LCD_DisplayOff(void); void LCD_Clear(uint16_t Color); void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos); void LCD_DrawPoint(uint16_t x,uint16_t y);//画点 void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); void LCD_SetWindows(uint16_t xStar, uint16_t yStar,uint16_t xEnd,uint16_t yEnd); void LCD_WriteReg(uint8_t LCD_Reg, uint16_t LCD_RegValue); void LCD_WR_DATA(uint8_t data); void LCD_WriteRAM_Prepare(void); void LCD_WriteRAM(uint16_t RGB_Code); uint16_t LCD_ReadRAM(void); uint16_t LCD_BGR2RGB(uint16_t c); void LCD_SetParam(void); void LCD_WriteData_16Bit(uint16_t Data); void LCD_direction(uint8_t direction); ////////////////////////////////////////////////////////////////// /*GUI*/ ////////////////////////////////////////////////////////////////// void GUI_DrawPoint(uint16_t x,uint16_t y,uint16_t color); void LCD_Fill(uint16_t sx,uint16_t sy,uint16_t ex,uint16_t ey,uint16_t color); void LCD_DrawLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); void Draw_Triangel(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2); void Fill_Triangel(uint16_t x0,uint16_t y0,uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2); void Draw_Circle(uint16_t x0,uint16_t y0,uint16_t fc,uint8_t r); void LCD_ShowChar(uint16_t x,uint16_t y,uint16_t fc, uint16_t bc, uint8_t num,uint8_t size,uint8_t mode); void LCD_ShowNum(uint16_t x,uint16_t y,uint32_t num,uint8_t len,uint8_t size); void LCD_Show2Num(uint16_t x,uint16_t y,uint16_t num,uint8_t len,uint8_t size,uint8_t mode); void LCD_ShowString(uint16_t x,uint16_t y,uint8_t size,uint8_t *p,uint8_t mode); void GUI_DrawFont16(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s,uint8_t mode); void GUI_DrawFont24(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s,uint8_t mode); void GUI_DrawFont32(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *s,uint8_t mode); void Show_Str(uint16_t x, uint16_t y, uint16_t fc, uint16_t bc, uint8_t *str,uint8_t size,uint8_t mode); void Gui_Drawbmp16(uint16_t x,uint16_t y,uint16_t w, uint16_t h, const unsigned char *p); //显示40*40 QQ图片 void gui_circle(int32_t xc, int32_t yc,uint16_t c,int32_t r, int32_t fill); void Gui_StrCenter(int16_t x, int16_t y, uint16_t fc, uint16_t bc, uint8_t *str,uint8_t size,uint8_t mode); void LCD_DrawFillRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2); ////////////////////////////////////////////////////////////////// /*tsstGUI*/ ////////////////////////////////////////////////////////////////// void DrawTestPage(uint8_t *str); void Display_ButtonUp(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2); void menu_test(void); void Test_Color(void); void Test_FillRec(void); void Test_Circle(void); void Test_Triangle(void); void English_Font_test(void); void Chinese_Font_test(void); void Pic_test(void); void Load_Drow_Dialog(void); void Touch_Test(void); void main_test(void); void Rotate_Test(void); void Test_Dynamic_Num(void); #endif   font.h代码如下: #ifndef __FONT_H #define __FONT_H //常用ASCII表 //偏移量32 //ASCII字符集 //偏移量32 //大小:12*6 //字体:Default //逐行式,逆向(低位在前) const unsigned char asc2_1206[95][12]={ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/ {0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x04,0x00,0x00},/*"!",1*/ {0x00,0x14,0x0A,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/ {0x00,0x00,0x14,0x14,0x3F,0x14,0x0A,0x3F,0x0A,0x0A,0x00,0x00},/*"#",3*/ {0x00,0x04,0x1E,0x15,0x05,0x06,0x0C,0x14,0x15,0x0F,0x04,0x00},/*"$",4*/ {0x00,0x00,0x12,0x15,0x0D,0x0A,0x14,0x2C,0x2A,0x12,0x00,0x00},/*"%",5*/ {0x00,0x00,0x04,0x0A,0x0A,0x1E,0x15,0x15,0x09,0x36,0x00,0x00},/*"&",6*/ {0x00,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/ {0x00,0x20,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x20,0x00},/*"(",8*/ {0x00,0x02,0x04,0x08,0x08,0x08,0x08,0x08,0x08,0x04,0x02,0x00},/*")",9*/ {0x00,0x00,0x00,0x04,0x15,0x0E,0x0E,0x15,0x04,0x00,0x00,0x00},/*"*",10*/ {0x00,0x00,0x04,0x04,0x04,0x1F,0x04,0x04,0x04,0x00,0x00,0x00},/*"+",11*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x01},/*",",12*/ {0x00,0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",13*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00},/*".",14*/ {0x00,0x10,0x08,0x08,0x08,0x04,0x04,0x02,0x02,0x02,0x01,0x00},/*"/",15*/ {0x00,0x00,0x0E,0x11,0x11,0x11,0x11,0x11,0x11,0x0E,0x00,0x00},/*"0",16*/ {0x00,0x00,0x04,0x06,0x04,0x04,0x04,0x04,0x04,0x0E,0x00,0x00},/*"1",17*/ {0x00,0x00,0x0E,0x11,0x11,0x08,0x04,0x02,0x01,0x1F,0x00,0x00},/*"2",18*/ {0x00,0x00,0x0E,0x11,0x10,0x0C,0x10,0x10,0x11,0x0E,0x00,0x00},/*"3",19*/ {0x00,0x00,0x08,0x0C,0x0A,0x0A,0x09,0x1E,0x08,0x18,0x00,0x00},/*"4",20*/ {0x00,0x00,0x1F,0x01,0x01,0x0F,0x10,0x10,0x11,0x0E,0x00,0x00},/*"5",21*/ {0x00,0x00,0x0E,0x09,0x01,0x0F,0x11,0x11,0x11,0x0E,0x00,0x00},/*"6",22*/ {0x00,0x00,0x1F,0x09,0x08,0x04,0x04,0x04,0x04,0x04,0x00,0x00},/*"7",23*/ {0x00,0x00,0x0E,0x11,0x11,0x0E,0x11,0x11,0x11,0x0E,0x00,0x00},/*"8",24*/ {0x00,0x00,0x0E,0x11,0x11,0x11,0x1E,0x10,0x12,0x0E,0x00,0x00},/*"9",25*/ {0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x04,0x00,0x00},/*":",26*/ {0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x04,0x04,0x00},/*";",27*/ {0x00,0x20,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x20,0x00,0x00},/*"<",28*/ {0x00,0x00,0x00,0x00,0x1F,0x00,0x00,0x1F,0x00,0x00,0x00,0x00},/*"=",29*/ {0x00,0x02,0x04,0x08,0x10,0x20,0x10,0x08,0x04,0x02,0x00,0x00},/*">",30*/ {0x00,0x00,0x0E,0x11,0x11,0x08,0x04,0x04,0x00,0x04,0x00,0x00},/*"?",31*/ {0x00,0x00,0x0E,0x11,0x19,0x15,0x15,0x1D,0x01,0x1E,0x00,0x00},/*"@",32*/ {0x00,0x00,0x04,0x04,0x0C,0x0A,0x0A,0x1E,0x12,0x33,0x00,0x00},/*"A",33*/ {0x00,0x00,0x0F,0x12,0x12,0x0E,0x12,0x12,0x12,0x0F,0x00,0x00},/*"B",34*/ {0x00,0x00,0x1E,0x11,0x01,0x01,0x01,0x01,0x11,0x0E,0x00,0x00},/*"C",35*/ {0x00,0x00,0x0F,0x12,0x12,0x12,0x12,0x12,0x12,0x0F,0x00,0x00},/*"D",36*/ {0x00,0x00,0x1F,0x12,0x0A,0x0E,0x0A,0x02,0x12,0x1F,0x00,0x00},/*"E",37*/ {0x00,0x00,0x1F,0x12,0x0A,0x0E,0x0A,0x02,0x02,0x07,0x00,0x00},/*"F",38*/ {0x00,0x00,0x1C,0x12,0x01,0x01,0x39,0x11,0x12,0x0C,0x00,0x00},/*"G",39*/ {0x00,0x00,0x33,0x12,0x12,0x1E,0x12,0x12,0x12,0x33,0x00,0x00},/*"H",40*/ {0x00,0x00,0x1F,0x04,0x04,0x04,0x04,0x04,0x04,0x1F,0x00,0x00},/*"I",41*/ {0x00,0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08,0x09,0x07,0x00},/*"J",42*/ {0x00,0x00,0x37,0x12,0x0A,0x06,0x0A,0x0A,0x12,0x37,0x00,0x00},/*"K",43*/ {0x00,0x00,0x07,0x02,0x02,0x02,0x02,0x02,0x22,0x3F,0x00,0x00},/*"L",44*/ {0x00,0x00,0x1B,0x1B,0x1B,0x1B,0x15,0x15,0x15,0x15,0x00,0x00},/*"M",45*/ {0x00,0x00,0x3B,0x12,0x16,0x16,0x1A,0x1A,0x12,0x17,0x00,0x00},/*"N",46*/ {0x00,0x00,0x0E,0x11,0x11,0x11,0x11,0x11,0x11,0x0E,0x00,0x00},/*"O",47*/ {0x00,0x00,0x0F,0x12,0x12,0x0E,0x02,0x02,0x02,0x07,0x00,0x00},/*"P",48*/ {0x00,0x00,0x0E,0x11,0x11,0x11,0x11,0x17,0x19,0x0E,0x18,0x00},/*"Q",49*/ {0x00,0x00,0x0F,0x12,0x12,0x0E,0x0A,0x12,0x12,0x37,0x00,0x00},/*"R",50*/ {0x00,0x00,0x1E,0x11,0x01,0x06,0x08,0x10,0x11,0x0F,0x00,0x00},/*"S",51*/ {0x00,0x00,0x1F,0x15,0x04,0x04,0x04,0x04,0x04,0x0E,0x00,0x00},/*"T",52*/ {0x00,0x00,0x33,0x12,0x12,0x12,0x12,0x12,0x12,0x0C,0x00,0x00},/*"U",53*/ {0x00,0x00,0x33,0x12,0x12,0x0A,0x0A,0x0C,0x04,0x04,0x00,0x00},/*"V",54*/ {0x00,0x00,0x15,0x15,0x15,0x0E,0x0A,0x0A,0x0A,0x0A,0x00,0x00},/*"W",55*/ {0x00,0x00,0x1B,0x0A,0x0A,0x04,0x04,0x0A,0x0A,0x1B,0x00,0x00},/*"X",56*/ {0x00,0x00,0x1B,0x0A,0x0A,0x04,0x04,0x04,0x04,0x0E,0x00,0x00},/*"Y",57*/ {0x00,0x00,0x1F,0x09,0x08,0x04,0x04,0x02,0x12,0x1F,0x00,0x00},/*"Z",58*/ {0x00,0x1C,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x1C,0x00},/*"[",59*/ {0x00,0x02,0x02,0x02,0x04,0x04,0x08,0x08,0x08,0x10,0x00,0x00},/*"\",60*/ {0x00,0x0E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0E,0x00},/*"]",61*/ {0x00,0x04,0x0A,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F},/*"_",63*/ {0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/ {0x00,0x00,0x00,0x00,0x00,0x0C,0x12,0x1C,0x12,0x3C,0x00,0x00},/*"a",65*/ {0x00,0x00,0x03,0x02,0x02,0x0E,0x12,0x12,0x12,0x0E,0x00,0x00},/*"b",66*/ {0x00,0x00,0x00,0x00,0x00,0x1C,0x12,0x02,0x02,0x1C,0x00,0x00},/*"c",67*/ {0x00,0x00,0x18,0x10,0x10,0x1C,0x12,0x12,0x12,0x3C,0x00,0x00},/*"d",68*/ {0x00,0x00,0x00,0x00,0x00,0x0C,0x12,0x1E,0x02,0x1C,0x00,0x00},/*"e",69*/ {0x00,0x00,0x38,0x04,0x04,0x1E,0x04,0x04,0x04,0x1E,0x00,0x00},/*"f",70*/ {0x00,0x00,0x00,0x00,0x00,0x3C,0x12,0x0C,0x02,0x1E,0x22,0x1C},/*"g",71*/ {0x00,0x00,0x03,0x02,0x02,0x0E,0x12,0x12,0x12,0x37,0x00,0x00},/*"h",72*/ {0x00,0x00,0x04,0x00,0x00,0x06,0x04,0x04,0x04,0x0E,0x00,0x00},/*"i",73*/ {0x00,0x00,0x08,0x00,0x00,0x0C,0x08,0x08,0x08,0x08,0x08,0x07},/*"j",74*/ {0x00,0x00,0x03,0x02,0x02,0x3A,0x0A,0x0E,0x12,0x37,0x00,0x00},/*"k",75*/ {0x00,0x00,0x07,0x04,0x04,0x04,0x04,0x04,0x04,0x1F,0x00,0x00},/*"l",76*/ {0x00,0x00,0x00,0x00,0x00,0x0F,0x15,0x15,0x15,0x15,0x00,0x00},/*"m",77*/ {0x00,0x00,0x00,0x00,0x00,0x0F,0x12,0x12,0x12,0x37,0x00,0x00},/*"n",78*/ {0x00,0x00,0x00,0x00,0x00,0x0C,0x12,0x12,0x12,0x0C,0x00,0x00},/*"o",79*/ {0x00,0x00,0x00,0x00,0x00,0x0F,0x12,0x12,0x12,0x0E,0x02,0x07},/*"p",80*/ {0x00,0x00,0x00,0x00,0x00,0x1C,0x12,0x12,0x12,0x1C,0x10,0x38},/*"q",81*/ {0x00,0x00,0x00,0x00,0x00,0x1B,0x06,0x02,0x02,0x07,0x00,0x00},/*"r",82*/ {0x00,0x00,0x00,0x00,0x00,0x1E,0x02,0x0C,0x10,0x1E,0x00,0x00},/*"s",83*/ {0x00,0x00,0x00,0x04,0x04,0x0E,0x04,0x04,0x04,0x18,0x00,0x00},/*"t",84*/ {0x00,0x00,0x00,0x00,0x00,0x1B,0x12,0x12,0x12,0x3C,0x00,0x00},/*"u",85*/ {0x00,0x00,0x00,0x00,0x00,0x37,0x12,0x0A,0x0C,0x04,0x00,0x00},/*"v",86*/ {0x00,0x00,0x00,0x00,0x00,0x15,0x15,0x0E,0x0A,0x0A,0x00,0x00},/*"w",87*/ {0x00,0x00,0x00,0x00,0x00,0x1B,0x0A,0x04,0x0A,0x1B,0x00,0x00},/*"x",88*/ {0x00,0x00,0x00,0x00,0x00,0x37,0x12,0x0A,0x0C,0x04,0x04,0x03},/*"y",89*/ {0x00,0x00,0x00,0x00,0x00,0x1E,0x08,0x04,0x04,0x1E,0x00,0x00},/*"z",90*/ {0x00,0x18,0x08,0x08,0x08,0x04,0x08,0x08,0x08,0x08,0x18,0x00},/*"{",91*/ {0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08},/*"|",92*/ {0x00,0x06,0x04,0x04,0x04,0x08,0x04,0x04,0x04,0x04,0x06,0x00},/*"}",93*/ {0x02,0x25,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} /*"~",94*/ }; //常用ASCII表 //偏移量32 //ASCII字符集 //偏移量32 //大小:16*8 //字体:Default //逐行式,逆向(低位在前) const unsigned char asc2_1608[95][16]={ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/ {0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x18,0x18,0x00,0x00},/*"!",1*/ {0x00,0x48,0x6C,0x24,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/ {0x00,0x00,0x00,0x24,0x24,0x24,0x7F,0x12,0x12,0x12,0x7F,0x12,0x12,0x12,0x00,0x00},/*"#",3*/ {0x00,0x00,0x08,0x1C,0x2A,0x2A,0x0A,0x0C,0x18,0x28,0x28,0x2A,0x2A,0x1C,0x08,0x08},/*"$",4*/ {0x00,0x00,0x00,0x22,0x25,0x15,0x15,0x15,0x2A,0x58,0x54,0x54,0x54,0x22,0x00,0x00},/*"%",5*/ {0x00,0x00,0x00,0x0C,0x12,0x12,0x12,0x0A,0x76,0x25,0x29,0x11,0x91,0x6E,0x00,0x00},/*"&",6*/ {0x00,0x06,0x06,0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/ {0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40,0x00},/*"(",8*/ {0x00,0x02,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x08,0x04,0x02,0x00},/*")",9*/ {0x00,0x00,0x00,0x00,0x08,0x08,0x6B,0x1C,0x1C,0x6B,0x08,0x08,0x00,0x00,0x00,0x00},/*"*",10*/ {0x00,0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x7F,0x08,0x08,0x08,0x08,0x00,0x00,0x00},/*"+",11*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x04,0x03},/*",",12*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",13*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x00,0x00},/*".",14*/ {0x00,0x00,0x80,0x40,0x40,0x20,0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x02,0x02,0x00},/*"/",15*/ {0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00},/*"0",16*/ {0x00,0x00,0x00,0x08,0x0E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"1",17*/ {0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x20,0x20,0x10,0x08,0x04,0x42,0x7E,0x00,0x00},/*"2",18*/ {0x00,0x00,0x00,0x3C,0x42,0x42,0x20,0x18,0x20,0x40,0x40,0x42,0x22,0x1C,0x00,0x00},/*"3",19*/ {0x00,0x00,0x00,0x20,0x30,0x28,0x24,0x24,0x22,0x22,0x7E,0x20,0x20,0x78,0x00,0x00},/*"4",20*/ {0x00,0x00,0x00,0x7E,0x02,0x02,0x02,0x1A,0x26,0x40,0x40,0x42,0x22,0x1C,0x00,0x00},/*"5",21*/ {0x00,0x00,0x00,0x38,0x24,0x02,0x02,0x1A,0x26,0x42,0x42,0x42,0x24,0x18,0x00,0x00},/*"6",22*/ {0x00,0x00,0x00,0x7E,0x22,0x22,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00},/*"7",23*/ {0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00},/*"8",24*/ {0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x64,0x58,0x40,0x40,0x24,0x1C,0x00,0x00},/*"9",25*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00},/*":",26*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x04},/*";",27*/ {0x00,0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x20,0x40,0x00,0x00},/*"<",28*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x00,0x00},/*"=",29*/ {0x00,0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x00},/*">",30*/ {0x00,0x00,0x00,0x3C,0x42,0x42,0x46,0x40,0x20,0x10,0x10,0x00,0x18,0x18,0x00,0x00},/*"?",31*/ {0x00,0x00,0x00,0x1C,0x22,0x5A,0x55,0x55,0x55,0x55,0x2D,0x42,0x22,0x1C,0x00,0x00},/*"@",32*/ {0x00,0x00,0x00,0x08,0x08,0x18,0x14,0x14,0x24,0x3C,0x22,0x42,0x42,0xE7,0x00,0x00},/*"A",33*/ {0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x1E,0x22,0x42,0x42,0x42,0x22,0x1F,0x00,0x00},/*"B",34*/ {0x00,0x00,0x00,0x7C,0x42,0x42,0x01,0x01,0x01,0x01,0x01,0x42,0x22,0x1C,0x00,0x00},/*"C",35*/ {0x00,0x00,0x00,0x1F,0x22,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1F,0x00,0x00},/*"D",36*/ {0x00,0x00,0x00,0x3F,0x42,0x12,0x12,0x1E,0x12,0x12,0x02,0x42,0x42,0x3F,0x00,0x00},/*"E",37*/ {0x00,0x00,0x00,0x3F,0x42,0x12,0x12,0x1E,0x12,0x12,0x02,0x02,0x02,0x07,0x00,0x00},/*"F",38*/ {0x00,0x00,0x00,0x3C,0x22,0x22,0x01,0x01,0x01,0x71,0x21,0x22,0x22,0x1C,0x00,0x00},/*"G",39*/ {0x00,0x00,0x00,0xE7,0x42,0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"H",40*/ {0x00,0x00,0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"I",41*/ {0x00,0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x0F},/*"J",42*/ {0x00,0x00,0x00,0x77,0x22,0x12,0x0A,0x0E,0x0A,0x12,0x12,0x22,0x22,0x77,0x00,0x00},/*"K",43*/ {0x00,0x00,0x00,0x07,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x42,0x7F,0x00,0x00},/*"L",44*/ {0x00,0x00,0x00,0x77,0x36,0x36,0x36,0x36,0x2A,0x2A,0x2A,0x2A,0x2A,0x6B,0x00,0x00},/*"M",45*/ {0x00,0x00,0x00,0xE3,0x46,0x46,0x4A,0x4A,0x52,0x52,0x52,0x62,0x62,0x47,0x00,0x00},/*"N",46*/ {0x00,0x00,0x00,0x1C,0x22,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x22,0x1C,0x00,0x00},/*"O",47*/ {0x00,0x00,0x00,0x3F,0x42,0x42,0x42,0x42,0x3E,0x02,0x02,0x02,0x02,0x07,0x00,0x00},/*"P",48*/ {0x00,0x00,0x00,0x1C,0x22,0x41,0x41,0x41,0x41,0x41,0x4D,0x53,0x32,0x1C,0x60,0x00},/*"Q",49*/ {0x00,0x00,0x00,0x3F,0x42,0x42,0x42,0x3E,0x12,0x12,0x22,0x22,0x42,0xC7,0x00,0x00},/*"R",50*/ {0x00,0x00,0x00,0x7C,0x42,0x42,0x02,0x04,0x18,0x20,0x40,0x42,0x42,0x3E,0x00,0x00},/*"S",51*/ {0x00,0x00,0x00,0x7F,0x49,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1C,0x00,0x00},/*"T",52*/ {0x00,0x00,0x00,0xE7,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00},/*"U",53*/ {0x00,0x00,0x00,0xE7,0x42,0x42,0x22,0x24,0x24,0x14,0x14,0x18,0x08,0x08,0x00,0x00},/*"V",54*/ {0x00,0x00,0x00,0x6B,0x49,0x49,0x49,0x49,0x55,0x55,0x36,0x22,0x22,0x22,0x00,0x00},/*"W",55*/ {0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x18,0x18,0x18,0x24,0x24,0x42,0xE7,0x00,0x00},/*"X",56*/ {0x00,0x00,0x00,0x77,0x22,0x22,0x14,0x14,0x08,0x08,0x08,0x08,0x08,0x1C,0x00,0x00},/*"Y",57*/ {0x00,0x00,0x00,0x7E,0x21,0x20,0x10,0x10,0x08,0x04,0x04,0x42,0x42,0x3F,0x00,0x00},/*"Z",58*/ {0x00,0x78,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x78,0x00},/*"[",59*/ {0x00,0x00,0x02,0x02,0x04,0x04,0x08,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x40,0x40},/*"\",60*/ {0x00,0x1E,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1E,0x00},/*"]",61*/ {0x00,0x38,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF},/*"_",63*/ {0x00,0x06,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x78,0x44,0x42,0x42,0xFC,0x00,0x00},/*"a",65*/ {0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x1A,0x26,0x42,0x42,0x42,0x26,0x1A,0x00,0x00},/*"b",66*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x02,0x02,0x02,0x44,0x38,0x00,0x00},/*"c",67*/ {0x00,0x00,0x00,0x60,0x40,0x40,0x40,0x78,0x44,0x42,0x42,0x42,0x64,0xD8,0x00,0x00},/*"d",68*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x7E,0x02,0x02,0x42,0x3C,0x00,0x00},/*"e",69*/ {0x00,0x00,0x00,0xF0,0x88,0x08,0x08,0x7E,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"f",70*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x22,0x22,0x1C,0x02,0x3C,0x42,0x42,0x3C},/*"g",71*/ {0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x3A,0x46,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"h",72*/ {0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x0E,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"i",73*/ {0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x22,0x1E},/*"j",74*/ {0x00,0x00,0x00,0x03,0x02,0x02,0x02,0x72,0x12,0x0A,0x16,0x12,0x22,0x77,0x00,0x00},/*"k",75*/ {0x00,0x00,0x00,0x0E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"l",76*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x92,0x92,0x92,0x92,0x92,0xB7,0x00,0x00},/*"m",77*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x46,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"n",78*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00},/*"o",79*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0x26,0x42,0x42,0x42,0x22,0x1E,0x02,0x07},/*"p",80*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x40,0xE0},/*"q",81*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x4C,0x04,0x04,0x04,0x04,0x1F,0x00,0x00},/*"r",82*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x42,0x02,0x3C,0x40,0x42,0x3E,0x00,0x00},/*"s",83*/ {0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x3E,0x08,0x08,0x08,0x08,0x08,0x30,0x00,0x00},/*"t",84*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x42,0x42,0x42,0x42,0x62,0xDC,0x00,0x00},/*"u",85*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x14,0x08,0x08,0x00,0x00},/*"v",86*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEB,0x49,0x49,0x55,0x55,0x22,0x22,0x00,0x00},/*"w",87*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0x24,0x18,0x18,0x18,0x24,0x6E,0x00,0x00},/*"x",88*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x14,0x18,0x08,0x08,0x07},/*"y",89*/ {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x22,0x10,0x08,0x08,0x44,0x7E,0x00,0x00},/*"z",90*/ {0x00,0xC0,0x20,0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0x20,0x20,0xC0,0x00},/*"{",91*/ {0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10},/*"|",92*/ {0x00,0x06,0x08,0x08,0x08,0x08,0x08,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x06,0x00},/*"}",93*/ {0x0C,0x32,0xC2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/ }; typedef struct { unsigned char Index[2]; char Msk[32]; }typFNT_GB16; //字体取模:宋体常规小四 //逐行式,顺向(高位在前) const typFNT_GB16 tfont16[]= { "电",0x00,0x00,0x01,0x00,0x01,0x00,0x1F,0xF0,0x61,0x0C,0x41,0x04,0x41,0x04,0x7F,0xFC, 0x41,0x04,0x41,0x04,0x41,0x04,0x7F,0xFC,0x01,0x00,0x01,0x02,0x01,0x02,0x01,0xFC,/*0*/ "电",0x00,0x00,0x01,0x00,0x01,0x00,0x1F,0xF0,0x61,0x0C,0x41,0x04,0x41,0x04,0x7F,0xFC, 0x41,0x04,0x41,0x04,0x41,0x04,0x7F,0xFC,0x01,0x00,0x01,0x02,0x01,0x02,0x01,0xFC,/*1*/ "电",0x00,0x00,0x01,0x00,0x01,0x00,0x1F,0xF0,0x61,0x0C,0x41,0x04,0x41,0x04,0x7F,0xFC, 0x41,0x04,0x41,0x04,0x41,0x04,0x7F,0xFC,0x01,0x00,0x01,0x02,0x01,0x02,0x01,0xFC,/*2*/ "电",0x00,0x00,0x01,0x00,0x01,0x00,0x1F,0xF0,0x61,0x0C,0x41,0x04,0x41,0x04,0x7F,0xFC, 0x41,0x04,0x41,0x04,0x41,0x04,0x7F,0xFC,0x01,0x00,0x01,0x02,0x01,0x02,0x01,0xFC,/*0*/ "电",0x00,0x00,0x01,0x00,0x01,0x00,0x1F,0xF0,0x61,0x0C,0x41,0x04,0x41,0x04,0x7F,0xFC, 0x41,0x04,0x41,0x04,0x41,0x04,0x7F,0xFC,0x01,0x00,0x01,0x02,0x01,0x02,0x01,0xFC,/*1*/ "电",0x00,0x00,0x01,0x00,0x01,0x00,0x1F,0xF0,0x61,0x0C,0x41,0x04,0x41,0x04,0x7F,0xFC, 0x41,0x04,0x41,0x04,0x41,0x04,0x7F,0xFC,0x01,0x00,0x01,0x02,0x01,0x02,0x01,0xFC,/*2*/ "子",0x00,0x00,0x00,0x00,0x3F,0xF8,0x00,0x10,0x00,0x60,0x00,0x80,0x01,0x00,0x00,0x80, 0x7F,0xFE,0x00,0x40,0x00,0x40,0x00,0x20,0x00,0x20,0x00,0x20,0x18,0x40,0x07,0x80,/*3*/ "技",0x10,0x20,0x10,0x20,0x10,0x20,0x13,0xFE,0xFC,0x20,0x10,0x20,0x10,0x20,0x15,0xFC,0x18,0x84,0x30,0x88,0xD0,0x48,0x10,0x50,0x10,0x20,0x10,0x50,0x51,0x88,0x26,0x06, "术",0x01,0x00,0x01,0x20,0x01,0x10,0x01,0x10,0x7F,0xFC,0x03,0x80,0x05,0x40,0x05,0x40,0x09,0x20,0x11,0x10,0x21,0x08,0x41,0x04,0x81,0x02,0x01,0x00,0x01,0x00,0x01,0x00, "有",0x02,0x00,0x02,0x00,0xFF,0xFE,0x04,0x00,0x04,0x00,0x0F,0xF0,0x08,0x10,0x18,0x10,0x2F,0xF0,0x48,0x10,0x88,0x10,0x0F,0xF0,0x08,0x10,0x08,0x10,0x08,0x50,0x08,0x20, "限",0x00,0x00,0x7B,0xF8,0x4A,0x08,0x52,0x08,0x53,0xF8,0x62,0x08,0x52,0x08,0x4B,0xF8,0x4A,0x44,0x4A,0x48,0x6A,0x30,0x52,0x20,0x42,0x10,0x42,0x88,0x43,0x06,0x42,0x00, "公",0x00,0x80,0x04,0x80,0x04,0x80,0x08,0x40,0x08,0x40,0x10,0x20,0x20,0x10,0x42,0x08,0x82,0x06,0x04,0x00,0x04,0x40,0x08,0x20,0x10,0x20,0x3F,0xF0,0x10,0x10,0x00,0x00, "司",0x00,0x00,0x3F,0xF8,0x00,0x08,0x00,0x08,0x7F,0xE8,0x00,0x08,0x00,0x08,0x1F,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x1F,0x88,0x10,0x88,0x00,0x28,0x00,0x10, "欢",0x00,0x80,0x00,0x80,0xFC,0x80,0x04,0xFC,0x05,0x04,0x49,0x08,0x2A,0x40,0x14,0x40,0x10,0x40,0x28,0xA0,0x24,0xA0,0x45,0x10,0x81,0x10,0x02,0x08,0x04,0x04,0x08,0x02, "迎",0x00,0x00,0x20,0x80,0x13,0x3C,0x12,0x24,0x02,0x24,0x02,0x24,0xF2,0x24,0x12,0x24,0x12,0x24,0x12,0xB4,0x13,0x28,0x12,0x20,0x10,0x20,0x28,0x20,0x47,0xFE,0x00,0x00, "您",0x09,0x00,0x09,0x00,0x11,0xFC,0x32,0x04,0x54,0x48,0x99,0x50,0x11,0x48,0x12,0x44,0x14,0x44,0x11,0x40,0x10,0x80,0x02,0x00,0x51,0x04,0x51,0x12,0x90,0x12,0x0F,0xF0, "纯",0x00,0x00,0x00,0x20,0x10,0x20,0x13,0xFE,0x20,0x20,0x26,0x24,0x4A,0x24,0x7A,0x24, 0x12,0x24,0x22,0x24,0x23,0xFC,0x7C,0x20,0x00,0x22,0x04,0x22,0x78,0x22,0x00,0x3C,/*0*/ "色",0x00,0x00,0x00,0x00,0x04,0x00,0x0F,0xF0,0x10,0x20,0x20,0x20,0x7F,0xFC,0x20,0x84, 0x20,0x84,0x20,0x84,0x20,0x84,0x3F,0xF8,0x20,0x00,0x20,0x02,0x20,0x02,0x1F,0xFE,/*1*/ "填",0x00,0x00,0x00,0x00,0x20,0x40,0x23,0xFE,0x20,0x40,0x79,0xFC,0x22,0x04,0x23,0xFC, 0x22,0x04,0x23,0xFC,0x22,0x04,0x23,0xFC,0x3A,0x04,0x65,0xFA,0x01,0x98,0x02,0x04,/*2*/ "充",0x00,0x00,0x01,0x00,0x01,0x00,0x7F,0xFE,0x02,0x20,0x04,0x10,0x04,0x08,0x08,0x04, 0x3F,0xFC,0x04,0x42,0x04,0x40,0x04,0x40,0x04,0x42,0x08,0x42,0x10,0x42,0x60,0x7E,/*3*/ "矩",0x00,0x00,0x00,0x00,0x20,0x7E,0x3E,0x80,0x48,0x80,0x48,0x80,0x48,0xFE,0x48,0x82, 0x7F,0x82,0x08,0x82,0x0C,0x82,0x14,0xFA,0x12,0x84,0x22,0x80,0x21,0x80,0x40,0xFE,/*6*/ "形",0x00,0x00,0x00,0x00,0x7F,0x84,0x22,0x08,0x22,0x30,0x22,0xC0,0x22,0x02,0x22,0x04, 0x7F,0xC8,0x22,0x30,0x22,0xC2,0x22,0x02,0x22,0x04,0x22,0x08,0x22,0x30,0x40,0x40,/*7*/ "画",0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x0F,0xF0,0x11,0x10,0x11,0x10,0x11,0x10, 0x51,0x12,0x5F,0xF2,0x51,0x12,0x51,0x12,0x51,0x12,0x4F,0xF2,0x40,0x02,0x7F,0xFC,/*8*/ "圆",0x00,0x00,0x00,0x00,0x7F,0xFE,0x47,0xE2,0x48,0x12,0x48,0x12,0x47,0xE2,0x4F,0xF2, 0x50,0x12,0x50,0x12,0x51,0x12,0x51,0x12,0x42,0x92,0x44,0x72,0x58,0x0A,0x3F,0xFC,/*9*/ "图",0x00,0x00,0x00,0x00,0x3F,0xFE,0x44,0x02,0x47,0xF2,0x4C,0x22,0x53,0x62,0x40,0x82, 0x43,0x62,0x5E,0x1A,0x41,0x82,0x40,0x62,0x43,0x02,0x40,0xC2,0x40,0x22,0x3F,0xFC,/*0*/ "片",0x00,0x00,0x00,0x40,0x20,0x40,0x20,0x40,0x20,0x40,0x3F,0xFE,0x20,0x00,0x20,0x00, 0x20,0x00,0x3F,0xE0,0x20,0x10,0x20,0x10,0x20,0x10,0x20,0x10,0x40,0x10,0x40,0x10,/*1*/ "显",0x00,0x00,0x00,0x00,0x3F,0xFC,0x20,0x04,0x20,0x04,0x3F,0xFC,0x20,0x04,0x20,0x04, 0x1F,0xF8,0x24,0x44,0x14,0x48,0x14,0x48,0x14,0x48,0x0C,0x50,0x04,0x40,0x7F,0xFE,/*2*/ "示",0x00,0x00,0x00,0x00,0x3F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x80, 0x08,0x90,0x08,0x88,0x10,0x88,0x10,0x84,0x20,0x84,0x20,0x82,0x40,0x82,0x07,0x80,/*3*/ "菜",0x00,0x00,0x00,0x20,0x08,0x20,0x7F,0xFE,0x00,0x20,0x00,0x78,0x3F,0x88,0x11,0x08, 0x08,0x90,0x09,0x20,0x7F,0xFE,0x01,0x80,0x03,0x40,0x0D,0x30,0x31,0x0C,0x40,0x02,/*4*/ "单",0x00,0x00,0x00,0x10,0x08,0x10,0x04,0x20,0x3F,0xF8,0x21,0x04,0x21,0x04,0x3F,0xFC, 0x21,0x04,0x21,0x04,0x3F,0xF8,0x01,0x00,0x7F,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,/*5*/ "中",0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x3F,0xFC,0x21,0x04,0x21,0x04,0x21,0x04, 0x21,0x04,0x21,0x04,0x21,0x04,0x3F,0xFC,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,/*0*/ "英",0x00,0x00,0x00,0x00,0x08,0x20,0x7F,0xFE,0x08,0x20,0x09,0x20,0x01,0x00,0x3F,0xF8, 0x21,0x08,0x21,0x08,0x21,0x08,0x1F,0xF4,0x01,0x40,0x02,0x20,0x0C,0x10,0x70,0x0E,/*1*/ "文",0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x80,0x3F,0x7C,0x08,0x10,0x08,0x10,0x04,0x10, 0x04,0x20,0x02,0x20,0x02,0x40,0x01,0x80,0x01,0x80,0x02,0x60,0x1C,0x18,0xE0,0x06,/*2*/ "综",0x00,0x00,0x00,0x00,0x10,0x20,0x11,0xFE,0x22,0x02,0x22,0x02,0x49,0xFC,0x58,0x00, 0x30,0x00,0x13,0xFE,0x25,0x28,0x79,0x24,0x01,0x24,0x0D,0x24,0x72,0x22,0x02,0xA2,/*4*/ "合",0x00,0x00,0x00,0x00,0x01,0x80,0x02,0x40,0x04,0x30,0x18,0x08,0x60,0x06,0x1F,0xF8, 0x00,0x00,0x1F,0xF8,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x1F,0xF8,/*5*/ "亮",0x00,0x00,0x01,0x00,0x01,0x00,0x7F,0xFE,0x00,0x00,0x3F,0xF8,0x20,0x08,0x3F,0xF8, 0x3F,0xF8,0x40,0x06,0x47,0xC2,0x48,0x24,0x08,0x20,0x08,0x22,0x10,0x22,0x60,0x3E,/*0*/ "度",0x00,0x00,0x00,0x00,0x00,0x80,0x3F,0xFE,0x44,0x10,0x5F,0xFC,0x44,0x10,0x44,0x10, 0x43,0xF0,0x40,0x00,0x5F,0xF8,0x44,0x08,0x42,0x30,0x41,0xC0,0x43,0x60,0xBC,0x1E,/*1*/ "测",0x00,0x00,0x00,0x00,0x67,0xC2,0x14,0x52,0x05,0x52,0x05,0x52,0xC5,0x52,0x25,0x52, 0x05,0x52,0x05,0x52,0x15,0x52,0x17,0x52,0x22,0x82,0x22,0x42,0x44,0x42,0x48,0x3E,/*2*/ "试",0x00,0x00,0x00,0x00,0x20,0x14,0x10,0x14,0x17,0xFE,0x00,0x12,0x00,0x10,0x60,0x10, 0x13,0xF0,0x10,0x90,0x10,0x90,0x10,0x90,0x14,0x92,0x14,0xEA,0x1F,0x0A,0x00,0x06,/*3*/ "程",0x00,0x00,0x00,0x00,0x19,0xFE,0x72,0x02,0x12,0x02,0x12,0x02,0x7D,0xFC,0x18,0x00, 0x1B,0xFE,0x34,0x20,0x50,0x20,0x53,0xFE,0x10,0x20,0x10,0x20,0x10,0x20,0x13,0xFE,/*8*/ "序",0x00,0x00,0x00,0x00,0x00,0x80,0x3F,0xFE,0x40,0x00,0x47,0xFC,0x42,0x08,0x41,0x30, 0x40,0xC0,0x5F,0xFE,0x40,0x42,0x40,0x42,0x40,0x44,0x40,0x48,0x40,0x40,0x44,0x40,/*9*/ "调",0x00,0x00,0x00,0x00,0x23,0xFE,0x12,0x22,0x02,0xFA,0x02,0x22,0xE2,0x22,0x12,0xFE, 0x12,0x72,0x12,0x8A,0x12,0x8A,0x12,0x8A,0x16,0xBA,0x1A,0x42,0x12,0x02,0x04,0x0E,/*0*/ "光",0x00,0x00,0x01,0x00,0x01,0x04,0x11,0x08,0x09,0x08,0x09,0x10,0x09,0x20,0x7F,0xFE, 0x04,0x40,0x04,0x40,0x04,0x40,0x04,0x40,0x08,0x42,0x08,0x42,0x10,0x42,0x60,0x7C,/*1*/ "版",0x00,0x00,0x00,0x00,0x48,0xFE,0x49,0x00,0x49,0x00,0x49,0x00,0x7E,0xFE,0x41,0x82, 0x41,0x44,0x79,0x44,0x45,0x28,0x45,0x28,0x45,0x10,0x45,0x28,0x46,0x44,0x03,0x82,/*10*/ "权",0x00,0x00,0x10,0x00,0x10,0x00,0x13,0xFC,0x7D,0x04,0x11,0x04,0x19,0x04,0x18,0x84, 0x34,0x88,0x50,0x48,0x50,0x50,0x10,0x20,0x10,0x50,0x10,0x88,0x13,0x04,0x14,0x02,/*11*/ "所",0x00,0x00,0x00,0x00,0x3F,0x7C,0x20,0x40,0x20,0x40,0x3E,0x40,0x22,0x7E,0x22,0x44, 0x22,0x44,0x22,0x44,0x3E,0x84,0x20,0x84,0x20,0x84,0x40,0x84,0x41,0x04,0x42,0x04,/*12*/ "屏",0x00,0x00,0x3F,0xF8,0x20,0x08,0x20,0x08,0x3F,0xF8,0x24,0x10,0x22,0x20,0x2F,0xF8, 0x22,0x20,0x22,0x20,0x3F,0xFC,0x22,0x20,0x42,0x20,0x44,0x20,0x84,0x20,0x08,0x20,/*"?",0*/ "幕",0x04,0x40,0x7F,0xFC,0x04,0x40,0x1F,0xF0,0x10,0x10,0x1F,0xF0,0x10,0x10,0x1F,0xF0, 0x04,0x00,0xFF,0xFE,0x11,0x10,0x3F,0xF8,0xD1,0x16,0x11,0x50,0x11,0x20,0x01,0x00,/*"?",1*/ "旋",0x20,0x80,0x10,0x80,0x10,0xFE,0x01,0x00,0xFE,0x00,0x21,0xFC,0x20,0x24,0x3C,0x24, 0x24,0xA0,0x24,0xA0,0x24,0xBC,0x24,0xA0,0x24,0xA0,0x45,0x60,0x55,0x3E,0x8A,0x00,/*"?",2*/ "转",0x20,0x20,0x20,0x20,0x20,0x20,0xFD,0xFC,0x40,0x20,0x50,0x40,0x93,0xFE,0xFC,0x40, 0x10,0x80,0x11,0xFC,0x1C,0x04,0xF0,0x88,0x50,0x50,0x10,0x20,0x10,0x10,0x10,0x10,/*"?",3*/ "开",0x00,0x00,0x7F,0xFC,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0xFF,0xFE, 0x08,0x20,0x08,0x20,0x08,0x20,0x08,0x20,0x10,0x20,0x10,0x20,0x20,0x20,0x40,0x20,/*"?",0*/ "源",0x00,0x00,0x27,0xFE,0x14,0x20,0x14,0x40,0x85,0xFC,0x45,0x04,0x45,0xFC,0x15,0x04, 0x15,0xFC,0x25,0x24,0xE4,0x20,0x24,0xA8,0x29,0x24,0x2A,0x22,0x30,0xA0,0x00,0x40,/*"?",1*/ "液",0x00,0x80,0x20,0x40,0x17,0xFE,0x11,0x20,0x81,0x20,0x42,0x3C,0x42,0x44,0x16,0x64, 0x12,0x94,0x23,0x48,0xE2,0x48,0x22,0x30,0x22,0x20,0x22,0x50,0x22,0x88,0x03,0x06,/*"?",2*/ "晶",0x0F,0xE0,0x08,0x20,0x08,0x20,0x0F,0xE0,0x08,0x20,0x08,0x20,0x0F,0xE0,0x00,0x00, 0x7E,0xFC,0x42,0x84,0x42,0x84,0x7E,0xFC,0x42,0x84,0x42,0x84,0x7E,0xFC,0x42,0x84,/*"?",3*/ "网",0x00,0x00,0x7F,0xFC,0x40,0x04,0x40,0x04,0x42,0x14,0x52,0x94,0x4A,0x54,0x44,0x24, 0x44,0x24,0x4A,0x54,0x4A,0x54,0x52,0x94,0x61,0x04,0x40,0x04,0x40,0x14,0x40,0x08,/*"?",4*/ "站",0x10,0x20,0x08,0x20,0x08,0x20,0x7E,0x20,0x00,0x3E,0x04,0x20,0x44,0x20,0x44,0x20, 0x25,0xFC,0x29,0x04,0x29,0x04,0x0F,0x04,0xF1,0x04,0x41,0x04,0x01,0xFC,0x01,0x04,/*"?",5*/ "按",0x10,0x40,0x10,0x20,0x10,0x20,0x13,0xFE,0xFA,0x02,0x14,0x44,0x10,0x40,0x1B,0xFE, 0x30,0x88,0xD0,0x88,0x11,0x08,0x10,0xD0,0x10,0x20,0x10,0x50,0x50,0x88,0x23,0x04,/*"?",6*/ "键",0x20,0x10,0x20,0x10,0x3B,0x7C,0x21,0x14,0x41,0xFE,0x7A,0x14,0xA2,0x7C,0x27,0x10, 0xF9,0x7C,0x25,0x10,0x25,0xFE,0x22,0x10,0x2A,0x10,0x35,0x00,0x28,0xFE,0x00,0x00,/*"?",0*/ "校",0x10,0x40,0x10,0x20,0x10,0x20,0x11,0xFE,0xFC,0x00,0x10,0x88,0x31,0x04,0x3A,0x02, 0x54,0x88,0x50,0x88,0x90,0x50,0x10,0x50,0x10,0x20,0x10,0x50,0x10,0x88,0x13,0x06,/*"?",7*/ "准",0x01,0x40,0x41,0x20,0x21,0x20,0x23,0xFE,0x02,0x20,0x16,0x20,0x1B,0xFC,0x12,0x20, 0x22,0x20,0x23,0xFC,0xE2,0x20,0x22,0x20,0x22,0x20,0x23,0xFE,0x22,0x00,0x02,0x00,/*"?",8*/ "触",0x20,0x20,0x20,0x20,0x78,0x20,0x49,0xFC,0x91,0x24,0x7D,0x24,0x55,0x24,0x55,0x24, 0x7D,0xFC,0x55,0x24,0x54,0x20,0x7C,0x28,0x54,0x24,0x57,0xFE,0x45,0x02,0x8C,0x00,/*"?",9*/ "摸",0x11,0x10,0x11,0x10,0x17,0xFC,0x11,0x10,0xFC,0x00,0x13,0xF8,0x12,0x08,0x17,0xF8, 0x1A,0x08,0x33,0xF8,0xD0,0x40,0x17,0xFC,0x10,0xA0,0x11,0x10,0x52,0x08,0x24,0x06,/*"?",10*/ "读",0x00,0x20,0x20,0x20,0x11,0xFC,0x10,0x20,0x00,0x20,0x03,0xFE,0xF0,0x02,0x10,0x94, 0x10,0x50,0x11,0x10,0x10,0x90,0x13,0xFE,0x14,0x28,0x18,0x44,0x10,0x82,0x03,0x02,/*"?",0*/ "和",0x04,0x00,0x0E,0x00,0x78,0x00,0x08,0x7C,0x08,0x44,0xFF,0x44,0x08,0x44,0x18,0x44, 0x1C,0x44,0x2A,0x44,0x2A,0x44,0x48,0x44,0x88,0x7C,0x08,0x44,0x08,0x00,0x08,0x00,/*"?",0*/ "颜",0x10,0x00,0x08,0xFE,0x7F,0x10,0x22,0x20,0x14,0x7C,0x7F,0x44,0x44,0x54,0x48,0x54, 0x52,0x54,0x44,0x54,0x48,0x54,0x51,0x54,0x42,0x28,0x44,0x24,0x88,0x42,0x30,0x82,/*"?",0*/ "值",0x08,0x40,0x08,0x40,0x0F,0xFC,0x10,0x40,0x10,0x40,0x33,0xF8,0x32,0x08,0x53,0xF8, 0x92,0x08,0x13,0xF8,0x12,0x08,0x13,0xF8,0x12,0x08,0x12,0x08,0x1F,0xFE,0x10,0x00,/*"?",0*/ "容",0x02,0x00,0x01,0x00,0x7F,0xFE,0x40,0x02,0x88,0x24,0x11,0x10,0x22,0x88,0x04,0x40, 0x08,0x20,0x30,0x18,0xDF,0xF6,0x10,0x10,0x10,0x10,0x10,0x10,0x1F,0xF0,0x10,0x10,/*"容",0*/ "支",0x01,0x00,0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x01,0x00,0x01,0x00,0x3F,0xF0, 0x10,0x10,0x08,0x20,0x04,0x40,0x02,0x80,0x01,0x00,0x06,0xC0,0x18,0x30,0xE0,0x0E,/*"支",1*/ "持",0x10,0x20,0x10,0x20,0x10,0x20,0x11,0xFC,0xFC,0x20,0x10,0x20,0x13,0xFE,0x10,0x08, 0x18,0x08,0x33,0xFE,0xD0,0x08,0x10,0x88,0x10,0x48,0x10,0x08,0x50,0x28,0x20,0x10,/*"持",2*/ "点",0x02,0x00,0x02,0x00,0x02,0x00,0x03,0xFC,0x02,0x00,0x02,0x00,0x3F,0xF0,0x20,0x10, 0x20,0x10,0x20,0x10,0x3F,0xF0,0x00,0x00,0x24,0x88,0x22,0x44,0x42,0x44,0x80,0x04,/*"点",3*/ "态",0x01,0x00,0x01,0x00,0x7F,0xFC,0x01,0x00,0x02,0x80,0x04,0x40,0x0A,0x20,0x31,0x18, 0xC0,0x06,0x01,0x00,0x08,0x88,0x48,0x84,0x48,0x12,0x48,0x12,0x87,0xF0,0x00,0x00,/*"态",0*/ "数",0x08,0x20,0x49,0x20,0x2A,0x20,0x08,0x3E,0xFF,0x44,0x2A,0x44,0x49,0x44,0x88,0xA4, 0x10,0x28,0xFE,0x28,0x22,0x10,0x42,0x10,0x64,0x28,0x18,0x28,0x34,0x44,0xC2,0x82,/*"数",1*/ "字",0x02,0x00,0x01,0x00,0x7F,0xFE,0x40,0x02,0x80,0x04,0x1F,0xE0,0x00,0x40,0x00,0x80, 0x01,0x00,0xFF,0xFE,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x05,0x00,0x02,0x00,/*"字",2*/ "退",0x03,0xF8,0x22,0x08,0x12,0x08,0x13,0xF8,0x02,0x08,0x02,0x08,0xF3,0xF8,0x12,0x44, 0x12,0x28,0x12,0x10,0x12,0x88,0x13,0x04,0x12,0x04,0x28,0x00,0x47,0xFE,0x00,0x00,/*"退",0*/ "出",0x01,0x00,0x01,0x00,0x21,0x08,0x21,0x08,0x21,0x08,0x21,0x08,0x3F,0xF8,0x01,0x08, 0x01,0x00,0x01,0x00,0x41,0x04,0x41,0x04,0x41,0x04,0x41,0x04,0x7F,0xFC,0x00,0x04,/*"出",1*/ }; typedef struct { unsigned char Index[2]; char Msk[72]; }typFNT_GB24; //字体取模:宋体常规小四 //逐行式,顺向(高位在前) const typFNT_GB24 tfont24[]= { "深",0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x08,0x0C,0x7F,0xFC,0x04, 0x40,0x10,0x01,0xC8,0xA0,0x02,0x18,0x60,0x42,0x30,0x18,0x32,0x23,0x18,0x12,0xC3, 0x00,0x14,0x03,0x00,0x04,0x03,0x0C,0x04,0x7F,0xF0,0x08,0x0F,0x80,0x08,0x0B,0x40, 0x78,0x13,0x60,0x18,0x33,0x20,0x18,0x63,0x18,0x18,0x83,0x1C,0x19,0x03,0x08,0x18, 0x03,0x00,0x00,0x03,0x00,0x00,0x00,0x00,/*0*/ "圳",0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x0C,0x04,0x18,0x0C,0x04,0x10,0x8C,0x04, 0x10,0x8C,0x04,0x10,0x8C,0x04,0x10,0x8C,0x04,0xD0,0x8C,0x3F,0x10,0x8C,0x04,0x10, 0x8C,0x04,0x10,0x8C,0x04,0x10,0x8C,0x04,0x10,0x8C,0x04,0x10,0x8C,0x04,0x10,0x8C, 0x05,0xF0,0x8C,0x0E,0x20,0x8C,0x78,0x20,0x8C,0x20,0x40,0x8C,0x00,0x80,0x8C,0x01, 0x00,0x0C,0x02,0x00,0x0C,0x00,0x00,0x00,/*1*/ "市",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x18,0x00,0x00,0x18,0x08,0x00, 0x00,0x1C,0x1F,0xFF,0xE0,0x00,0x18,0x00,0x00,0x18,0x20,0x07,0xFF,0xF0,0x04,0x18, 0x20,0x04,0x18,0x20,0x04,0x18,0x20,0x04,0x18,0x20,0x04,0x18,0x20,0x04,0x18,0x20, 0x04,0x18,0x20,0x04,0x18,0x20,0x04,0x18,0x20,0x04,0x18,0xE0,0x04,0x18,0x40,0x00, 0x18,0x00,0x00,0x18,0x00,0x00,0x00,0x00,/*2*/ "中",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00, 0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x3F,0xFF,0xFE,0x30,0x18,0x06,0x30,0x18, 0x06,0x30,0x18,0x06,0x30,0x18,0x06,0x30,0x18,0x06,0x3F,0xFF,0xFE,0x30,0x18,0x06, 0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*0*/ "文",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x1C,0x00,0x00, 0x06,0x00,0xFF,0xFF,0xFF,0x06,0x00,0x30,0x06,0x00,0x30,0x03,0x00,0x60,0x03,0x00, 0x60,0x01,0x80,0xC0,0x00,0xC1,0x80,0x00,0xE3,0x00,0x00,0x36,0x00,0x00,0x1C,0x00, 0x00,0x77,0x00,0x03,0xC1,0xE0,0x1E,0x00,0x3C,0x60,0x00,0x07,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*1*/ "测",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x03,0x21, 0xFF,0x33,0x39,0x83,0x33,0x11,0x83,0x33,0x01,0x9B,0x33,0xC1,0x9B,0x33,0x71,0x9B, 0x33,0x19,0x9B,0x33,0x01,0x9B,0x33,0x01,0x9B,0x33,0x11,0x9B,0x33,0x19,0xB3,0x33, 0x30,0x30,0x33,0x30,0x6C,0x03,0x30,0xC6,0x03,0x63,0x83,0x03,0x2E,0x01,0xBE,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*2*/ "试",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0xD8,0x30, 0x00,0xCE,0x18,0x00,0xC2,0x1C,0x00,0xC0,0x01,0xFF,0xFF,0x00,0x00,0xC0,0xF8,0x00, 0xC0,0x18,0x00,0xC0,0x19,0xFF,0xC0,0x18,0x18,0x40,0x18,0x18,0x60,0x19,0x18,0x60, 0x1B,0x18,0x61,0x1E,0x18,0x31,0x1C,0x1F,0xB1,0x39,0xF0,0x19,0x10,0x00,0x0F,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*3*/ }; typedef struct { unsigned char Index[2]; char Msk[128]; }typFNT_GB32; //字体取模:宋体常规小四 //逐行式,顺向(高位在前) const typFNT_GB32 tfont32[]= { "字",0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0xC0,0x00, 0x00,0x01,0xC0,0xC0,0x00,0x01,0x07,0xC0,0x00,0x01,0xFF,0x00,0x02,0x1F,0xFE,0x00, 0x07,0xF0,0x1C,0x00,0x07,0xC0,0x70,0x00,0x0F,0x00,0xE0,0x00,0x0E,0x03,0xF0,0x00, 0x1C,0x0F,0xF0,0x00,0x3C,0x0F,0x70,0x00,0x3C,0x00,0xE0,0x00,0x18,0x00,0xC0,0x00, 0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x20,0x00, 0x00,0x00,0x37,0x00,0x00,0x01,0xFF,0x00,0x00,0x7F,0xF8,0x00,0x07,0xF8,0x30,0x00, 0x1F,0x80,0x30,0x00,0x00,0x80,0x30,0x00,0x00,0xC0,0x30,0x00,0x00,0x60,0x60,0x00, 0x00,0x18,0xE0,0x00,0x00,0x0F,0xC0,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,/*0*/ "体",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xE0, 0x00,0x20,0x01,0xB8,0x00,0x70,0x3F,0xF8,0x00,0x61,0xFF,0xC0,0x00,0xC3,0x03,0x00, 0x01,0xC6,0x06,0x00,0x03,0x8C,0x06,0x00,0x03,0x08,0x0C,0x00,0x06,0x08,0x0C,0x00, 0x0E,0x18,0x18,0x3F,0x1E,0x10,0x1B,0xF3,0x1F,0x90,0x3F,0x07,0x00,0x80,0x3C,0x1C, 0x01,0x90,0x70,0x7C,0x01,0x90,0x60,0xFE,0x01,0xA0,0xC3,0xF8,0x01,0xA0,0x0F,0xD8, 0x03,0xA0,0x08,0x18,0x03,0x60,0x00,0x18,0x03,0x40,0x00,0x18,0x03,0xC0,0x00,0x18, 0x03,0x80,0x00,0x18,0x03,0x00,0x00,0x18,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x10, 0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*1*/ "测",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x02,0x0C,0x10,0x08,0x07,0x1F,0xF8,0x04,0x03,0xBF,0xF0,0x02,0x01,0xBC,0x30,0x03, 0x03,0xEC,0x30,0x03,0x01,0x5C,0x60,0x03,0x00,0xD8,0x60,0x03,0x00,0xD8,0x60,0x03, 0x80,0x98,0x62,0x03,0x61,0xB8,0x43,0x07,0x71,0xB1,0x43,0x06,0x31,0x32,0x43,0x06, 0x33,0x76,0xC3,0x06,0x3A,0x64,0xC7,0x06,0x3E,0xEC,0xC0,0x06,0x3E,0x78,0xC0,0x06, 0x3C,0x30,0x40,0x06,0x7C,0x70,0x00,0x06,0x78,0xE0,0x60,0x06,0x7B,0xFF,0xF0,0x06, 0xF7,0xC0,0x00,0x06,0xE4,0x00,0x00,0x06,0x40,0x00,0x00,0x06,0x00,0x00,0x00,0x06, 0x00,0x00,0x00,0x7C,0x00,0x00,0x8F,0xF0,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,/*2*/ "试",0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x00, 0x00,0x00,0x7F,0x80,0x00,0x00,0x01,0x80,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0, 0x00,0x00,0x00,0xCE,0x03,0x80,0x00,0xCF,0xFF,0xC0,0x00,0xDD,0x41,0x80,0x0F,0xFE, 0x00,0x07,0xFF,0xFC,0x00,0x0C,0x00,0xF0,0x00,0x18,0x0F,0xC0,0x3E,0x19,0xFF,0x40, 0xF3,0x11,0xBC,0x60,0x83,0x30,0x7F,0xE0,0x03,0xB1,0xFE,0x20,0x03,0x33,0x80,0x20, 0x03,0x70,0x00,0x30,0x03,0x60,0x00,0x10,0x03,0x60,0x00,0x18,0x07,0xC0,0x00,0x0C, 0x07,0xC0,0x00,0x04,0x07,0x80,0x00,0x02,0x01,0x00,0x00,0x03,0x00,0x00,0x00,0x01, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*3*/ }; #endif main.c代码如下: /* USER CODE BEGIN Header */ /** ****************************************************************************** * @File : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" #include "lcd.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ ADC_HandleTypeDef hadc1; SPI_HandleTypeDef hspi1; UART_HandleTypeDef huart1; HCD_HandleTypeDef hhcd_USB_OTG_HS; /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void SystemPower_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); static void MX_ICACHE_Init(void); static void MX_UCPD1_Init(void); static void MX_USART1_UART_Init(void); static void MX_USB_OTG_HS_HCD_Init(void); static void MX_SPI1_Init(void); /* USER CODE BEGIN PFP */ /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* Configure the System Power */ SystemPower_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_ADC1_Init(); MX_ICACHE_Init(); MX_UCPD1_Init(); MX_USART1_UART_Init(); MX_USB_OTG_HS_HCD_Init(); MX_SPI1_Init(); /* USER CODE BEGIN 2 */ LCD_Init(); Gui_StrCenter(0,112,GREEN,BLUE,"HELLO EEWorld",16,1);//居中显示 Show_Str(70,146,BLUE,YELLOW,"HELLO EEWorld(^_^)",16,0); HAL_Delay(2000); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ main_test(); //测试主界面 menu_test(); //3D菜单显示测试 Test_Color(); //简单刷屏填充测试 Test_FillRec(); //GUI矩形绘图测试 Test_Circle(); //GUI画圆测试 Test_Triangle(); //GUI三角形绘图测试 English_Font_test();//英文字体示例测试 Chinese_Font_test();//中文字体示例测试 Pic_test(); //图片显示示例测试 Test_Dynamic_Num(); //动态数字显示 Rotate_Test(); //旋转显示测试 } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_MSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.MSIState = RCC_MSI_ON; RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV4; RCC_OscInitStruct.PLL.PLLM = 3; RCC_OscInitStruct.PLL.PLLN = 10; RCC_OscInitStruct.PLL.PLLP = 8; RCC_OscInitStruct.PLL.PLLQ = 2; RCC_OscInitStruct.PLL.PLLR = 1; RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; RCC_OscInitStruct.PLL.PLLFRACN = 0; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2 |RCC_CLOCKTYPE_PCLK3; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { Error_Handler(); } } /** * @brief Power Configuration * @retval None */ static void SystemPower_Config(void) { HAL_PWREx_EnableVddIO2(); /* * Switch to SMPS regulator instead of LDO */ if (HAL_PWREx_ConfigSupply(PWR_SMPS_SUPPLY) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN PWR */ /* USER CODE END PWR */ } /** * @brief ADC1 Initialization Function * @param None * @retval None */ static void MX_ADC1_Init(void) { /* USER CODE BEGIN ADC1_Init 0 */ /* USER CODE END ADC1_Init 0 */ ADC_ChannelConfTypeDef sConfig = {0}; /* USER CODE BEGIN ADC1_Init 1 */ /* USER CODE END ADC1_Init 1 */ /** Common config */ hadc1.Instance = ADC1; hadc1.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1; hadc1.Init.Resolution = ADC_RESOLUTION_14B; hadc1.Init.GainCompensation = 0; hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc1.Init.LowPowerAutoWait = DISABLE; hadc1.Init.ContinuousConvMode = DISABLE; hadc1.Init.NbrOfConversion = 1; hadc1.Init.DiscontinuousConvMode = DISABLE; hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc1.Init.DMAContinuousRequests = DISABLE; hadc1.Init.TriggerFrequencyMode = ADC_TRIGGER_FREQ_HIGH; hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED; hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE; hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DR; hadc1.Init.OversamplingMode = DISABLE; if (HAL_ADC_Init(&hadc1) != HAL_OK) { Error_Handler(); } /** Configure Regular Channel */ sConfig.Channel = ADC_CHANNEL_3; sConfig.Rank = ADC_REGULAR_RANK_1; sConfig.SamplingTime = ADC_SAMPLETIME_5CYCLE; sConfig.SingleDiff = ADC_SINGLE_ENDED; sConfig.OffsetNumber = ADC_OFFSET_NONE; sConfig.Offset = 0; if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN ADC1_Init 2 */ /* USER CODE END ADC1_Init 2 */ } /** * @brief ICACHE Initialization Function * @param None * @retval None */ static void MX_ICACHE_Init(void) { /* USER CODE BEGIN ICACHE_Init 0 */ /* USER CODE END ICACHE_Init 0 */ /* USER CODE BEGIN ICACHE_Init 1 */ /* USER CODE END ICACHE_Init 1 */ /** Enable instruction cache in 1-way (direct mapped cache) */ if (HAL_ICACHE_ConfigAssociativityMode(ICACHE_1WAY) != HAL_OK) { Error_Handler(); } if (HAL_ICACHE_Enable() != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN ICACHE_Init 2 */ /* USER CODE END ICACHE_Init 2 */ } /** * @brief SPI1 Initialization Function * @param None * @retval None */ static void MX_SPI1_Init(void) { /* USER CODE BEGIN SPI1_Init 0 */ /* USER CODE END SPI1_Init 0 */ SPI_AutonomousModeConfTypeDef HAL_SPI_AutonomousMode_Cfg_Struct = {0}; /* USER CODE BEGIN SPI1_Init 1 */ /* USER CODE END SPI1_Init 1 */ /* SPI1 parameter configuration*/ hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES_TXONLY; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 0x7; hspi1.Init.NSSPMode = SPI_NSS_PULSE_ENABLE; hspi1.Init.NSSPolarity = SPI_NSS_POLARITY_LOW; hspi1.Init.FifoThreshold = SPI_FIFO_THRESHOLD_01DATA; hspi1.Init.MasterSSIdleness = SPI_MASTER_SS_IDLENESS_00CYCLE; hspi1.Init.MasterInterDataIdleness = SPI_MASTER_INTERDATA_IDLENESS_00CYCLE; hspi1.Init.MasterReceiverAutoSusp = SPI_MASTER_RX_AUTOSUSP_DISABLE; hspi1.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_DISABLE; hspi1.Init.IOSwap = SPI_IO_SWAP_DISABLE; hspi1.Init.ReadyMasterManagement = SPI_RDY_MASTER_MANAGEMENT_INTERNALLY; hspi1.Init.ReadyPolarity = SPI_RDY_POLARITY_HIGH; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } HAL_SPI_AutonomousMode_Cfg_Struct.TriggerState = SPI_AUTO_MODE_DISABLE; HAL_SPI_AutonomousMode_Cfg_Struct.TriggerSelection = SPI_GRP1_GPDMA_CH0_TCF_TRG; HAL_SPI_AutonomousMode_Cfg_Struct.TriggerPolarity = SPI_TRIG_POLARITY_RISING; if (HAL_SPIEx_SetConfigAutonomousMode(&hspi1, &HAL_SPI_AutonomousMode_Cfg_Struct) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN SPI1_Init 2 */ /* USER CODE END SPI1_Init 2 */ } /** * @brief UCPD1 Initialization Function * @param None * @retval None */ static void MX_UCPD1_Init(void) { /* USER CODE BEGIN UCPD1_Init 0 */ /* USER CODE END UCPD1_Init 0 */ LL_GPIO_InitTypeDef GPIO_InitStruct = {0}; /* Peripheral clock enable */ LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_UCPD1); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB); LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); /**UCPD1 GPIO Configuration PB15 ------> UCPD1_CC2 PA15 (JTDI) ------> UCPD1_CC1 */ GPIO_InitStruct.Pin = LL_GPIO_PIN_15; GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = LL_GPIO_PIN_15; GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = LL_GPIO_PULL_NO; LL_GPIO_Init(GPIOA, &GPIO_InitStruct); /* USER CODE BEGIN UCPD1_Init 1 */ /* USER CODE END UCPD1_Init 1 */ /* USER CODE BEGIN UCPD1_Init 2 */ /* USER CODE END UCPD1_Init 2 */ } /** * @brief USART1 Initialization Function * @param None * @retval None */ static void MX_USART1_UART_Init(void) { /* USER CODE BEGIN USART1_Init 0 */ /* USER CODE END USART1_Init 0 */ /* USER CODE BEGIN USART1_Init 1 */ /* USER CODE END USART1_Init 1 */ huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1; huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK) { Error_Handler(); } if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK) { Error_Handler(); } if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USART1_Init 2 */ /* USER CODE END USART1_Init 2 */ } /** * @brief USB_OTG_HS Initialization Function * @param None * @retval None */ static void MX_USB_OTG_HS_HCD_Init(void) { /* USER CODE BEGIN USB_OTG_HS_Init 0 */ /* USER CODE END USB_OTG_HS_Init 0 */ /* USER CODE BEGIN USB_OTG_HS_Init 1 */ /* USER CODE END USB_OTG_HS_Init 1 */ hhcd_USB_OTG_HS.Instance = USB_OTG_HS; hhcd_USB_OTG_HS.Init.Host_channels = 16; hhcd_USB_OTG_HS.Init.speed = HCD_SPEED_HIGH; hhcd_USB_OTG_HS.Init.dma_enable = DISABLE; hhcd_USB_OTG_HS.Init.phy_itface = USB_OTG_HS_EMBEDDED_PHY; hhcd_USB_OTG_HS.Init.Sof_enable = DISABLE; hhcd_USB_OTG_HS.Init.low_power_enable = DISABLE; hhcd_USB_OTG_HS.Init.use_external_vbus = ENABLE; if (HAL_HCD_Init(&hhcd_USB_OTG_HS) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN USB_OTG_HS_Init 2 */ /* USER CODE END USB_OTG_HS_Init 2 */ } /** * @brief GPIO Initialization Function * @param None * @retval None */ static void MX_GPIO_Init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; /* USER CODE BEGIN MX_GPIO_Init_1 */ /* USER CODE END MX_GPIO_Init_1 */ /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOC_CLK_ENABLE(); __HAL_RCC_GPIOH_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOF_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); __HAL_RCC_GPIOG_CLK_ENABLE(); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LCD_BL_GPIO_Port, LCD_BL_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin, GPIO_PIN_RESET); /*Configure GPIO pin Output Level */ HAL_GPIO_WritePin(GPIOB, UCPD_DBn_Pin|LED_BLUE_Pin|LCD_RST_Pin|LCD_DC_Pin, GPIO_PIN_RESET); /*Configure GPIO pin : USER_BUTTON_Pin */ GPIO_InitStruct.Pin = USER_BUTTON_Pin; GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(USER_BUTTON_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : LCD_CS_Pin */ GPIO_InitStruct.Pin = LCD_CS_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(LCD_CS_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : LCD_BL_Pin */ GPIO_InitStruct.Pin = LCD_BL_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(LCD_BL_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : UCPD_FLT_Pin */ GPIO_InitStruct.Pin = UCPD_FLT_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(UCPD_FLT_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : LED_RED_Pin */ GPIO_InitStruct.Pin = LED_RED_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LED_RED_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pin : LED_GREEN_Pin */ GPIO_InitStruct.Pin = LED_GREEN_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(LED_GREEN_GPIO_Port, &GPIO_InitStruct); /*Configure GPIO pins : UCPD_DBn_Pin LED_BLUE_Pin */ GPIO_InitStruct.Pin = UCPD_DBn_Pin|LED_BLUE_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /*Configure GPIO pins : LCD_RST_Pin LCD_DC_Pin */ GPIO_InitStruct.Pin = LCD_RST_Pin|LCD_DC_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE END MX_GPIO_Init_2 */ } /* USER CODE BEGIN 4 */ /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */  

  • 2024-03-08
  • 发表了主题帖: 【ST NUCLEO-U5A5ZJ-Q开发板测评】4、ADC+DMA

    STM32U5系列的资料:STM32U595/5A5: 相关PDF文档 STM32U5系列的DMA GPDMA可以同时处理16个独立的数据传输任务,每个通道都有其自己的FIFO队列,用于排队源和目标传输。 通过可编程的GPDMA输入触发器与GPDMA任务完成事件的连接,可以实现通道间和通道内的传输链接。 对于每个链表项,可以单独编程源和目标传输,还可以编程源和目标之间的数据处理方式,如字节重排、打包或解包、填充或截断、符号扩展和左右对齐。 支持scatter-gather (multi-buffer transfers)     Continuous Conversion Mode:连续转换模式:使能 DMA Continuous Requests:DMA连续请求:使能   Go to GPDMA1   开启中断   配置链表:     串口打印ADC采样值,并转换为电压值,板载PC2测量的是VBUS_SENSE,ADC测量未接入TypeC时电压是0V,接入后是0.67V;     我的是cubeMX6.8.1生成的工程,没有链表头文件和ADC的VDDA电压开启,所以都需要单独引入和打开 程序首先引用头文件   /* USER CODE BEGIN Includes */ #include "stdio.h" #include "linked_list.h" /* USER CODE END Includes */ 串口重定义,并且外部调用linked_list链表中的声明变量,定义一个转化数组 #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF); return ch; } extern DMA_NodeTypeDef ADCNode; extern DMA_QListTypeDef ADCQueue; extern ADC_HandleTypeDef hadc1; extern DMA_HandleTypeDef handle_GPDMA1_Channel10; #define ADC_CONVERTED_DATA_BUFFER_SIZE ((uint32_t) 32) /* Size of array aADCxConvertedData[] */ /* Variable containing ADC conversions data */ uint32_t aADCxConvertedData[ADC_CONVERTED_DATA_BUFFE 在main函数中配置ADC,并将ADC与链表进行链接 HAL_PWREx_EnableVddA(); MX_ADCQueue_Config(); __HAL_LINKDMA(&hadc1, DMA_Handle, handle_GPDMA1_Channel10); if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel10, &ADCQueue) != HAL_OK) { Error_Handler(); } if (HAL_ADC_Start_DMA(&hadc1,(uint32_t *)aADCxConvertedData,(ADC_CONVERTED_DATA_BUFFER_SIZE)) != HAL_OK) { Error_Handler(); } 在while(1)中 printf("ADC VaL:%ld voltage:%.4f \r\n ", aADCxConvertedData[0], (float)(aADCxConvertedData[0])*3.3/16384);        

  • 2024-03-01
  • 发表了主题帖: 【得捷Follow me第4期】项目总结

    本帖最后由 chrisrh 于 2024-3-1 16:16 编辑 对Follow me4项目的过往进行总结 因为是第一次应用树莓派的RP2040,很多地方比较生疏,所以选择了最为官方推荐的方案 W5500-EVB-Pico、 Adafruit Sharp Memory Display,跟在大家的后面,一起学习进步。 这次收获满满,认识了RP2040,了解了micro python和circuit python编程的方便,更是学到了许多TCP/IP相关的知识,收益颇丰! 汇总视频:  [localvideo]734f95f1a03aed506a2d528cf748f4f6[/localvideo]   一、入门任务: 1、开发环境搭建,这里选择了micro python和circuit python进行后续工作,刷写固件也很方便 [localvideo]438af3cd8c3c32578b35dda4ab92de6c[/localvideo]   2、LED灯BLINK闪闪,驱动液晶显示器进行显示 【得捷电子Follow me第4期】入门任务-开箱-开发环境搭建-BLINK - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn) import machine import time # 初始化LED引脚为输出模式 led = machine.Pin('LED', machine.Pin.OUT) while True: # 点亮LED led.on() time.sleep(1) # 等待1秒钟 # 熄灭LED led.off() time.sleep(1) # 等待1秒钟 3、驱动sharp的lcd屏幕,显示信息 【得捷电子Follow me第4期】入门任务->基础任务一 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn) import sys import time import board import digitalio import busio import adafruit_sharpmemorydisplay # 打印输入到stdout print("start:xxx") # 初始化LED引脚 led = digitalio.DigitalInOut(board.GP25) led.direction = digitalio.Direction.OUTPUT # Initialize SPI bus and control pins spi = busio.SPI(board.GP14, MOSI=board.GP15) scs = digitalio.DigitalInOut(board.GP13) # inverted chip select # pass in the display size, width and height, as well # display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96) display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 144, 168) print("Pixel test") # Clear the display. Always call show after changing pixels to make the display # update visible! display.fill(1) display.show() # Set a pixel in the origin 0,0 position. display.pixel(0, 0, 0) # Set a pixel in the middle position. display.pixel(display.width // 2, display.width // 2, 0) # Set a pixel in the opposite corner position. display.pixel(display.width - 1, display.height - 1, 0) display.show() time.sleep(2) print("Lines test") # we'll draw from corner to corner, lets define all the pair coordinates here corners = ( (0, 0), (0, display.height - 1), (display.width - 1, 0), (display.width - 1, display.height - 1), ) display.fill(1) for corner_from in corners: for corner_to in corners: display.line(corner_from[0], corner_from[1], corner_to[0], corner_to[1], 0) display.show() time.sleep(2) print("Rectangle test") display.fill(1) w_delta = display.width / 10 h_delta = display.height / 10 for i in range(11): display.rect(0, 0, int(w_delta * i), int(h_delta * i), 0) display.show() time.sleep(2) print("Text test") display.fill(1) display.text(" hello world!", 0, 0, 0) display.text(" This is the", 0, 8, 0) display.text(" CircuitPython", 0, 16, 0) display.text("adafruit library", 0, 24, 0) display.text(" for the SHARP", 0, 32, 0) display.text(" Memory Display :) ", 0, 40, 0) display.show() # 循环使能LED点亮 while True: # 点亮LED led.value = True time.sleep(1) led.value = False time.sleep(1) [localvideo]8c4f9807b74cc482cbf1da7733eeeac7[/localvideo]   二、基础任务一 完成主控板W5500初始化(静态IP配置),并能使用局域网电脑ping通,同时W5500可以ping通互联网站点;通过抓包软件(Wireshark、Sniffer等)抓取ping报文析。 【得捷电子Follow me第4期】入门任务->基础任务一 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn) import board import busio import digitalio import time from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K ##SPI0 SPI0_SCK = board.GP18 SPI0_TX = board.GP19 SPI0_RX = board.GP16 SPI0_CSn = board.GP17 ##reset W5x00_RSTn = board.GP20 print("Wiznet5k Ping Test (no DHCP)") # Setup your network configuration below # random MAC, later should change this value on your vendor ID MY_MAC = (0x00, 0x01, 0x02, 0x03, 0x04, 0x05) IP_ADDRESS = (192, 168, 1, 100) SUBNET_MASK = (255, 255, 255, 0) GATEWAY_ADDRESS = (192, 168, 1, 1) DNS_SERVER = (8, 8, 8, 8) led = digitalio.DigitalInOut(board.GP25) led.direction = digitalio.Direction.OUTPUT ethernetRst = digitalio.DigitalInOut(W5x00_RSTn) ethernetRst.direction = digitalio.Direction.OUTPUT # For Adafruit Ethernet FeatherWing cs = digitalio.DigitalInOut(SPI0_CSn) # For Particle Ethernet FeatherWing # cs = digitalio.DigitalInOut(board.D5) spi_bus = busio.SPI(SPI0_SCK, MOSI=SPI0_TX, MISO=SPI0_RX) # Reset W5500 first ethernetRst.value = False time.sleep(1) ethernetRst.value = True # Initialize ethernet interface with DHCP # eth = WIZNET5K(spi_bus, cs) # Initialize ethernet interface without DHCP eth = WIZNET5K(spi_bus, cs, is_dhcp=False, mac=MY_MAC) # Set network configuration eth.ifconfig = (IP_ADDRESS, SUBNET_MASK, GATEWAY_ADDRESS, DNS_SERVER) print("Chip Version:", eth.chip) print("MAC Address:", [hex(i) for i in eth.mac_address]) print("My IP address is:", eth.pretty_ip(eth.ip_address)) while True: led.value = not led.value time.sleep(1) print("Done!") 设置静态IP: IP_ADDRESS = (192, 168, 1, 100) SUBNET_MASK = (255, 255, 255, 0) GATEWAY_ADDRESS = (192, 168, 1, 1)   同一路由下,本机的IP为192.168.1.33,然后在CMD中使用ping  192, 168, 1, 100完成静态IP的ping [localvideo]8e8a93b5cd7a4666128c793d99a62b23[/localvideo]   三、基础任务二 主控板建立TCP/IP或UDP服务器,使用TCP/IP或UDP客户端进行连接与发送数据,主控板接收数据并显示,通过抓包软件抓取交互报文 【得捷电子Follow me第4期】基础任务二-TCP server和UDP server - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn) 3.1、TCP Server 将pico+W5500通过网线接到路由或者交换机上,这里主机地址是192.168.31.171 将pico+W5500配置为192.168.31.100,端口号2233 import board import busio import digitalio import time import array from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket import adafruit_sharpmemorydisplay '''LED init''' led = digitalio.DigitalInOut(board.GP25) led.direction = digitalio.Direction.OUTPUT '''Sharp Display init''' # Initialize SPI bus and control pins spi = busio.SPI(board.GP14, MOSI=board.GP15) scs = digitalio.DigitalInOut(board.GP13) # inverted chip select # pass in the display size, width and height, as well # display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96) display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 144, 168) '''W5500 init start''' ##SPI0-W5500 SPI0_SCK = board.GP18 SPI0_TX = board.GP19 SPI0_RX = board.GP16 SPI0_CSn = board.GP17 ##reset W5x00_RSTn = board.GP20 print("Wiznet5k Simple TCP Server Test") # Setup your network configuration below # random MAC, later should change this value on your vendor ID #MY_MAC = (0x00, 0x01, 0x02, 0x03, 0x04, 0x05) IP_ADDRESS = (192, 168, 31, 100) SUBNET_MASK = (255, 255, 0, 0) GATEWAY_ADDRESS = (192, 168, 31, 1) DNS_SERVER = (8, 8, 8, 8) ethernetRst = digitalio.DigitalInOut(W5x00_RSTn) ethernetRst.direction = digitalio.Direction.OUTPUT # For Adafruit Ethernet FeatherWing cs = digitalio.DigitalInOut(SPI0_CSn) # For Particle Ethernet FeatherWing # cs = digitalio.DigitalInOut(board.D5) spi_bus = busio.SPI(SPI0_SCK, MOSI=SPI0_TX, MISO=SPI0_RX) # Reset W5500 first ethernetRst.value = False time.sleep(1) ethernetRst.value = True # # Initialize ethernet interface without DHCP eth = WIZNET5K(spi_bus, cs, is_dhcp=False)#, mac=MY_MAC, debug=True) # # Set network configuration eth.ifconfig = (IP_ADDRESS, SUBNET_MASK, GATEWAY_ADDRESS, DNS_SERVER) # Initialize ethernet interface with DHCP #eth = WIZNET5K(spi_bus, cs, is_dhcp=True, mac=MY_MAC, debug=True) print("Chip Version:", eth.chip) print("MAC Address:", [hex(i) for i in eth.mac_address]) print("My IP address is:", eth.pretty_ip(eth.ip_address)) '''W5500 init end''' '''TCP socket init''' # Initialize a socket for our server socket.set_interface(eth) server = socket.socket() # Allocate socket for the server server_ip = None # IP address of server server_port = 2233 # Port to listen on server.bind((server_ip, server_port)) # Bind to IP and Port server.listen() # Begin listening for incoming clients #conn, addr = server.accept() # Wait for a connection from a client. #print("socket connected") '''display show''' display.fill(1) chip_version = "chip version:" + eth.chip display.text(chip_version, 0, 0, 0) ip_addr = "ip:" + eth.pretty_ip(eth.ip_address) display.text(ip_addr, 0, 10, 0) mac_addr = "mac:" + eth.pretty_mac(eth.mac_address) display.text(mac_addr, 0, 20, 0) display.show() row = 30 print("socket connected") while True: # Maintain DHCP lease #eth.maintain_dhcp_lease() led.value = not led.value time.sleep(1) with server: while True: # data = conn.recv(20) data,addr = server.recvfrom(20) if data: print(data) display.fill_rect(0,row,144,10,1) display.text(data.decode('utf-8'), 0, row, 0) display.show() row += 10 if row > 150: row = 30 [localvideo]1d4b63bb7aececeb7df2d3273e73acfc[/localvideo] LCD显示传输数据 [localvideo]0ec79322a52acee7849673759a55ebb2[/localvideo]   3.2、UDP Server import board import busio import digitalio import time import array from adafruit_wiznet5k.adafruit_wiznet5k import WIZNET5K import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket import adafruit_sharpmemorydisplay '''LED init''' led = digitalio.DigitalInOut(board.GP25) led.direction = digitalio.Direction.OUTPUT '''Sharp Display init''' # Initialize SPI bus and control pins spi = busio.SPI(board.GP14, MOSI=board.GP15) scs = digitalio.DigitalInOut(board.GP13) # inverted chip select # pass in the display size, width and height, as well # display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96) display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 144, 168) '''W5500 init start''' ##SPI0-W5500 SPI0_SCK = board.GP18 SPI0_TX = board.GP19 SPI0_RX = board.GP16 SPI0_CSn = board.GP17 ##reset W5x00_RSTn = board.GP20 print("Wiznet5k Simple UDP Server Test") # Setup your network configuration below # random MAC, later should change this value on your vendor ID #MY_MAC = (0x00, 0x01, 0x02, 0x03, 0x04, 0x05) IP_ADDRESS = (192, 168, 31, 100) SUBNET_MASK = (255, 255, 0, 0) GATEWAY_ADDRESS = (192, 168, 31, 1) DNS_SERVER = (8, 8, 8, 8) ethernetRst = digitalio.DigitalInOut(W5x00_RSTn) ethernetRst.direction = digitalio.Direction.OUTPUT # For Adafruit Ethernet FeatherWing cs = digitalio.DigitalInOut(SPI0_CSn) # For Particle Ethernet FeatherWing # cs = digitalio.DigitalInOut(board.D5) spi_bus = busio.SPI(SPI0_SCK, MOSI=SPI0_TX, MISO=SPI0_RX) # Reset W5500 first ethernetRst.value = False time.sleep(1) ethernetRst.value = True # # Initialize ethernet interface without DHCP eth = WIZNET5K(spi_bus, cs, is_dhcp=False)#, mac=MY_MAC, debug=True) # # Set network configuration eth.ifconfig = (IP_ADDRESS, SUBNET_MASK, GATEWAY_ADDRESS, DNS_SERVER) # Initialize ethernet interface with DHCP #eth = WIZNET5K(spi_bus, cs, is_dhcp=True, mac=MY_MAC, debug=True) print("Chip Version:", eth.chip) print("MAC Address:", [hex(i) for i in eth.mac_address]) print("My IP address is:", eth.pretty_ip(eth.ip_address)) '''W5500 init end''' '''UDP socket init''' # Initialize a socket for our server socket.set_interface(eth) server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Allocate socket for the server server_ip = None # IP address of server server_port = 2233 # Port to listen on server.bind((eth.pretty_ip(eth.ip_address), server_port)) # Bind to IP and Port '''display show''' display.fill(1) chip_version = "chip version:" + eth.chip display.text(chip_version, 0, 0, 0) ip_addr = "ip:" + eth.pretty_ip(eth.ip_address) display.text(ip_addr, 0, 10, 0) mac_addr = "mac:" + eth.pretty_mac(eth.mac_address) display.text(mac_addr, 0, 20, 0) display.show() row = 30 print("socket connected") while True: # Maintain DHCP lease #eth.maintain_dhcp_lease() led.value = not led.value time.sleep(1) with server: while True: # data = conn.recv(20) data,addr = server.recvfrom(20) if data: print(data) display.fill_rect(0,row,144,10,1) display.text(data.decode('utf-8'), 0, row, 0) display.show() row += 10 if row > 150: row = 30 server.send(data) #conn.send(data) # Echo message back to client   四、进阶任务 从NTP服务器(注意数据交互格式的解析)同步时间,获取时间送显示屏(串口)显示 【得捷电子Follow me第4期】进阶任务-NTP同步时间 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn) 基于socket的示例,导入adafruit的ntp库,进行时间的获取与同步,import adafruit_ntp import board import busio import digitalio import time import array import struct import adafruit_requests as requests from adafruit_wiznet5k.adafruit_wiznet5k import * import adafruit_wiznet5k.adafruit_wiznet5k_socket as socket from adafruit_wiznet5k.adafruit_wiznet5k_ntp import NTP import adafruit_wiznet5k.adafruit_wiznet5k_dns as dns import adafruit_ntp days = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday") ##SPI0 SPI0_SCK = board.GP18 SPI0_TX = board.GP19 SPI0_RX = board.GP16 SPI0_CSn = board.GP17 ##reset W5x00_RSTn = board.GP20 print("Wiznet5k NTP Client (DHCP)") # Setup your network configuration below # random MAC, later should change this value on your vendor ID MY_MAC = (0x00, 0x01, 0x02, 0xFF, 0xFF, 0xFF) IP_ADDRESS = (192, 168, 1, 24) SUBNET_MASK = (255, 255, 255, 0) GATEWAY_ADDRESS = (192, 168, 1, 1) DNS_SERVER = (8, 8, 8, 8) port = 5000 ntp_server_port= 123 led = digitalio.DigitalInOut(board.GP25) led.direction = digitalio.Direction.OUTPUT ethernetRst = digitalio.DigitalInOut(W5x00_RSTn) ethernetRst.direction = digitalio.Direction.OUTPUT # For Adafruit Ethernet FeatherWing cs = digitalio.DigitalInOut(SPI0_CSn) # cs = digitalio.DigitalInOut(board.D5) spi_bus = busio.SPI(SPI0_SCK, MOSI=SPI0_TX, MISO=SPI0_RX) # Reset W5500 first ethernetRst.value = False time.sleep(1) ethernetRst.value = True # Initialize ethernet interface without DHCP #eth = WIZNET5K(spi_bus, cs, is_dhcp=False, mac=MY_MAC, debug=False) # Initialize ethernet interface with DHCP eth = WIZNET5K(spi_bus, cs, is_dhcp=True, mac=MY_MAC, debug=False) print("Chip Version:", eth.chip) print("MAC Address:", [hex(i) for i in eth.mac_address]) print("My IP address is:", eth.pretty_ip(eth.ip_address)) # Initialize a socket for our server socket.set_interface(eth) # Set network configuration eth.ifconfig = (IP_ADDRESS, SUBNET_MASK, GATEWAY_ADDRESS, DNS_SERVER) ntp = adafruit_ntp.NTP(socket) print(ntp.datetime) 通过串口打印出相关信息和+8后的时间:2024.2.16.23:59:44 [localvideo]180289930d2f4f4e0a147ffc48d0b3fc[/localvideo]   终极任务二 终极任务是使用外部存储器,组建简易FTP文件服务器,并能正常上传下载文件。 【得捷电子Follow me第4期】终极任务+总结 - DigiKey得捷技术专区 - 电子工程世界-论坛 (eeworld.com.cn) 这里借鉴并学习了其他小伙伴做的基于micropython的FTP服务器 import socket import network import uos import gc from time import localtime from machine import Pin,SPI import time def w5x00_init(): #spi init spi=SPI(0,2_000_000, mosi=Pin(19),miso=Pin(16),sck=Pin(18)) nic = network.WIZNET5K(spi,Pin(17),Pin(20)) #spi,cs,reset pin nic.active(True)#network active nic.ifconfig(('192.168.1.100','255.255.255.0','192.168.1.1','8.8.8.8'))#Set static network address information while not nic.isconnected(): time.sleep(1) print(nic.regs())#Print register information #Print network address information print("IP Address:",nic.ifconfig()[0]) print("Subnet Mask:",nic.ifconfig()[1]) print("Gateway:",nic.ifconfig()[2]) print("DNS:",nic.ifconfig()[3]) return nic month_name = ["", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] def send_list_data(path, dataclient, full): try: # whether path is a directory name for fname in uos.listdir(path): dataclient.sendall(make_description(path, fname, full)) except: # path may be a file name or pattern pattern = path.split("/")[-1] path = path[:-(len(pattern) + 1)] if path == "": path = "/" for fname in uos.listdir(path): if fncmp(fname, pattern) == True: dataclient.sendall(make_description(path, fname, full)) def make_description(path, fname, full): if full: stat = uos.stat(get_absolute_path(path,fname)) file_permissions = "drwxr-xr-x" if (stat[0] & 0o170000 == 0o040000) else "-rw-r--r--" file_size = stat[6] tm = localtime(stat[7]) if tm[0] != localtime()[0]: description = "{} 1 owner group {:>10} {} {:2} {:>5} {}\r\n".format( file_permissions, file_size, month_name[tm[1]], tm[2], tm[0], fname) else: description = "{} 1 owner group {:>10} {} {:2} {:02}:{:02} {}\r\n".format( file_permissions, file_size, month_name[tm[1]], tm[2], tm[3], tm[4], fname) else: description = fname + "\r\n" return description def send_file_data(path, dataclient): with open(path, "r") as file: chunk = file.read(512) while len(chunk) > 0: dataclient.sendall(chunk) chunk = file.read(512) def save_file_data(path, dataclient, mode): with open(path, mode) as file: chunk = dataclient.read(512) while len(chunk) > 0: file.write(chunk) chunk = dataclient.read(512) def get_absolute_path(cwd, payload): # Just a few special cases "..", "." and "" # If payload start's with /, set cwd to / # and consider the remainder a relative path if payload.startswith('/'): cwd = "/" for token in payload.split("/"): if token == '..': if cwd != '/': cwd = '/'.join(cwd.split('/')[:-1]) if cwd == '': cwd = '/' elif token != '.' and token != '': if cwd == '/': cwd += token else: cwd = cwd + '/' + token return cwd # compare fname against pattern. Pattern may contain # wildcards ? and *. def fncmp(fname, pattern): pi = 0 si = 0 while pi < len(pattern) and si < len(fname): if (fname[si] == pattern[pi]) or (pattern[pi] == '?'): si += 1 pi += 1 else: if pattern[pi] == '*': # recurse if (pi + 1) == len(pattern): return True while si < len(fname): if fncmp(fname[si:], pattern[pi+1:]) == True: return True else: si += 1 return False else: return False if pi == len(pattern.rstrip("*")) and si == len(fname): return True else: return False def ftpserver(): DATA_PORT = 13333 ftpsocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) datasocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) ftpsocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) datasocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ftpsocket.bind(socket.getaddrinfo("0.0.0.0", 21)[0][4]) datasocket.bind(socket.getaddrinfo("0.0.0.0", DATA_PORT)[0][4]) ftpsocket.listen(1) datasocket.listen(1) datasocket.settimeout(10) msg_250_OK = '250 OK\r\n' msg_550_fail = '550 Failed\r\n' try: dataclient = None fromname = None while True: cl, remote_addr = ftpsocket.accept() cl.settimeout(300) cwd = '/' try: # print("FTP connection from:", remote_addr) cl.sendall("220 Hello, this is the ESP8266.\r\n") while True: gc.collect() data = cl.readline().decode("utf-8").rstrip("\r\n") if len(data) <= 0: print("Client disappeared") break command = data.split(" ")[0].upper() payload = data[len(command):].lstrip() path = get_absolute_path(cwd, payload) print("Command={}, Payload={}, Path={}".format(command, payload, path)) if command == "USER": cl.sendall("230 Logged in.\r\n") elif command == "SYST": cl.sendall("215 UNIX Type: L8\r\n") elif command == "NOOP": cl.sendall("200 OK\r\n") elif command == "FEAT": cl.sendall("211 no-features\r\n") elif command == "PWD": cl.sendall('257 "{}"\r\n'.format(cwd)) elif command == "CWD": try: files = uos.listdir(path) cwd = path cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "CDUP": cwd = get_absolute_path(cwd, "..") cl.sendall(msg_250_OK) elif command == "TYPE": # probably should switch between binary and not cl.sendall('200 Transfer mode set\r\n') elif command == "SIZE": try: size = uos.stat(path)[6] cl.sendall('213 {}\r\n'.format(size)) except: cl.sendall(msg_550_fail) elif command == "QUIT": cl.sendall('221 Bye.\r\n') break elif command == "PASV": addr = nic.ifconfig()[0] cl.sendall('227 Entering Passive Mode ({},{},{}).\r\n'.format( addr.replace('.',','), DATA_PORT>>8, DATA_PORT%256)) dataclient, data_addr = datasocket.accept() # print("FTP Data connection from:", data_addr) elif command == "LIST" or command == "NLST": if not payload.startswith("-"): place = path else: place = cwd try: send_list_data(place, dataclient, command == "LIST" or payload == "-l") cl.sendall("150 Here comes the directory listing.\r\n") cl.sendall("226 Listed.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "RETR": try: send_file_data(path, dataclient) cl.sendall("150 Opening data connection.\r\n") cl.sendall("226 Transfer complete.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "STOR": try: cl.sendall("150 Ok to send data.\r\n") save_file_data(path, dataclient, "w") cl.sendall("226 Transfer complete.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "APPE": try: cl.sendall("150 Ok to send data.\r\n") save_file_data(path, dataclient, "a") cl.sendall("226 Transfer complete.\r\n") except: cl.sendall(msg_550_fail) if dataclient is not None: dataclient.close() dataclient = None elif command == "DELE": try: uos.remove(path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "RMD": try: uos.rmdir(path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "MKD": try: uos.mkdir(path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) elif command == "RNFR": fromname = path cl.sendall("350 Rename from\r\n") elif command == "RNTO": if fromname is not None: try: uos.rename(fromname, path) cl.sendall(msg_250_OK) except: cl.sendall(msg_550_fail) else: cl.sendall(msg_550_fail) fromname = None else: cl.sendall("502 Unsupported command.\r\n") # print("Unsupported command {} with payload {}".format(command, payload)) except Exception as err: print(err) finally: cl.close() cl = None finally: datasocket.close() ftpsocket.close() if dataclient is not None: dataclient.close() nic = w5x00_init() ftpserver() [localvideo]f8092654ff7a73d11dbfce9b20b4c2cb[/localvideo]     整个Follow me第四期下来,收获满满,自己作为小白,首先把pico裸机的外设端口学习了一遍,接着摸索着点亮了sharp的LCD屏幕,显示的那一瞬满是开心,也许电子这一行的快乐可能就是调通的那一刹那,后面在TCP/IP这块,配合着WiFi那块板子的调试进度,对client和servers有了更进一步的认知,在这块是真的学到了些许东西;最后的FTP服务器,自己没搞定,学习了论坛其他小伙伴的程序,后续随着自己的学习不断完善;     最后,谢谢得捷和EEworld的组织的这次活动,和给予的这次参与机会,组织的很棒。以后我会多加关注,积极参加论坛活动,多方面提升个人的知识,与大家一同进步,加油!    

  • 2024-02-27
  • 发表了主题帖: 【ST NUCLEO-U5A5ZJ-Q开发板测评】3、TIM和ADC

    本帖最后由 chrisrh 于 2024-2-27 13:29 编辑 定时器6中断 cubeMX配置定时器6中断,产生1ms的时基   在中断回调函数中tim6_count++计数: void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim == &htim6) { tim6_count++; } }     stm32cubeIDE开启浮点数的配置 cubeIDE未启用浮点输出,提示的警告: The float formatting support is not enabled, check your MCU Settings from "Project Properties > C/C++ Build > Settings > Tool Settings", or add manually "-u _printf_float" in linker flags. 通过修改属性进行消除:   选择"Properties"(属性)->  选择"C/C++ Build"(C/C++构建)->  展开"C/C++ Build"并选择"Settings"(设置),勾选printf float按钮,再重新编译工程,便可输出浮点数;       ADC采集VBUS+SENSE U5主打Ultra-low-power,这块有点不一样,各个部分的电源都可以单独使能控制;   我的cubeMX是6.8.0版本的···生成的工程中对PG2的RED灯还有ADC都没有开启Vdd; 6.9.0版本的cubemx生成的工程就没有问题了; 这里配置完,郁闷了一会,输出一直全0; 检查好久没找到原因;先前没有好好看手册,最后才发现是该部分的电源没开...   启动,按14位ADC配置,391.5Cycles   ★这里使能VddA模拟电: HAL_PWREx_EnableVddA();   ★这里使能PG2~15的供电VddIO2: HAL_PWREx_EnableVddIO2();   以下为可控制使能的Vdd电源:   5V_UCPD需要接入TYPE-C     配合着TIM6定时器的计数使用: if(0 == tim6_count%1000) { printf("tim6_count:%ld\r\n",tim6_count); HAL_ADC_Start(&hadc1); adc_val = HAL_ADC_GetValue(&hadc1); printf("ADC VaL: %d , %.3f\r\n", adc_val,(float)adc_val*3.3/16384); } 接入typeC供电和未接入TypeC供电电压,和实际测量对比,长采样周期时,测量值相一致; sConfig.SamplingTime = ADC_SAMPLETIME_5CYCLE;       sConfig.SamplingTime = ADC_SAMPLETIME_391CYCLES_5;        

  • 发表了主题帖: 【ST NUCLEO-U5A5ZJ-Q开发板测评】2、EXTI、PWM和串口的printf

    串口printf输出 Nucleo-U5A5的串口1和STlinkV3的串口相连,用以输出打印日志。 在cubeMX中开启串口1,在工程中重定向,就可以使用printf了 /* USER CODE BEGIN Includes */ #include "stdio.h" /* USER CODE END Includes */ #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF); return ch; }     User_key按键的外部中断   在cubeMX中的NVIC中enable按键的中断,并修改优先级高于systic,在stm32u5xx_it.c中可以看到EXTI13对应的中断接口函数 /** * [url=home.php?mod=space&uid=159083]@brief[/url] This function handles EXTI Line13 interrupt. */ void EXTI13_IRQHandler(void) { /* USER CODE BEGIN EXTI13_IRQn 0 */ /* USER CODE END EXTI13_IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(USER_BUTTON_Pin); /* USER CODE BEGIN EXTI13_IRQn 1 */ /* USER CODE END EXTI13_IRQn 1 */ } cubeMX生成代码中已写好gpio中断函数,清除相应的中断标志位,并弱定义了中断返回,使用时再重新书写中断返回函数HAL_GPIO_EXTI_Rising_Callback(GPIO_Pin);或HAL_GPIO_EXTI_Falling_Callback(GPIO_Pin);即可 void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin) { /* EXTI line interrupt detected */ if (__HAL_GPIO_EXTI_GET_RISING_IT(GPIO_Pin) != 0U) { __HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_Pin); HAL_GPIO_EXTI_Rising_Callback(GPIO_Pin); } if (__HAL_GPIO_EXTI_GET_FALLING_IT(GPIO_Pin) != 0U) { __HAL_GPIO_EXTI_CLEAR_FALLING_IT(GPIO_Pin); HAL_GPIO_EXTI_Falling_Callback(GPIO_Pin); } } 在main中定义EXTI13的中断返回函数,按下Blue翻转 void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == USER_BUTTON_Pin) { HAL_Delay(50); HAL_GPIO_TogglePin(LED_BLUE_GPIO_Port,LED_BLUE_Pin); printf("key exti callback\r\n"); } } 按键按下,BlueLED翻转     PWM输出呼吸灯 在cubeMX中配置GreenLED的定时器TIM3-Ch2   预分频(84-1,也就得到1MHz的时钟频率作为定时器的时钟源) 向上计数模式(从0开始向上计数至初值并发生上溢事件) 计数器重装值(500-1,每计数500次发生溢出,最终PWM频率为1M/500=2kHz) 内部时钟分频(可以理解为在预分频的基础上再进行一次分频,但只能2或4分频,这里不需要) 计数器自动重装载使能   开启全局中断   以上按160M/160=1M,1M/1000=1K的频率计数,实现呼吸灯效果 HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2); while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_Delay(5); if(dir)led0pwmval++; //dir==1 led0pwmval递增 else led0pwmval--; //dir==0 led0pwmval递减 if(led0pwmval>900)dir=0; //led0pwmval到达900后,方向为递减 if(led0pwmval==0)dir=1; //led0pwmval递减到0后,方向改为递增 __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,led0pwmval); } 启动定时器通道:HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2); PWM比较输出:__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,led0pwmval);     简单封装一下LED和PWM程序: 按键配合PWM程序,按键按下中断开启LED的PWM,再按下LED缓慢熄灭 /* USER CODE BEGIN Header */ /** ****************************************************************************** * [url=home.php?mod=space&uid=1307177]@File[/url] : main.c * @brief : Main program body ****************************************************************************** * [url=home.php?mod=space&uid=1020061]@attention[/url] * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "adc.h" #include "icache.h" #include "tim.h" #include "ucpd.h" #include "usart.h" #include "usb_otg.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "stdio.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void SystemPower_Config(void); /* USER CODE BEGIN PFP */ #ifdef __GNUC__ #define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endif PUTCHAR_PROTOTYPE { HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF); return ch; } /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ uint8_t dir=1; uint16_t led0pwmval=0; uint8_t pwmstate=1; uint32_t uwIC2Value1 = 0; uint32_t uwIC2Value2 = 0; uint32_t uwDiffCapture = 0; uint16_t uhCaptureIndex = 0; uint32_t uwFrequency = 0; uint32_t tim6_count = 0; /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ uint16_t adc_val; /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* Configure the System Power */ SystemPower_Config(); /* USER CODE BEGIN SysInit */ HAL_PWREx_EnableVddA(); HAL_PWREx_EnableVddIO2(); /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_ADC1_Init(); MX_ICACHE_Init(); MX_TIM3_Init(); MX_UCPD1_Init(); MX_USART1_UART_Init(); MX_USB_OTG_HS_HCD_Init(); MX_TIM1_Init(); MX_TIM6_Init(); /* USER CODE BEGIN 2 */ HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);//启动定时器PWM比较输出 HAL_TIM_Base_Start_IT(&htim6); //启定时器6中断 printf("start\r\n"); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ if(HAL_GPIO_ReadPin(LED_BLUE_GPIO_Port,LED_BLUE_Pin)) { LED_PWM(400); } else LED_PWM(0); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_MSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.MSIState = RCC_MSI_ON; RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT; RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_0; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI; RCC_OscInitStruct.PLL.PLLMBOOST = RCC_PLLMBOOST_DIV4; RCC_OscInitStruct.PLL.PLLM = 3; RCC_OscInitStruct.PLL.PLLN = 10; RCC_OscInitStruct.PLL.PLLP = 8; RCC_OscInitStruct.PLL.PLLQ = 2; RCC_OscInitStruct.PLL.PLLR = 1; RCC_OscInitStruct.PLL.PLLRGE = RCC_PLLVCIRANGE_1; RCC_OscInitStruct.PLL.PLLFRACN = 0; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2 |RCC_CLOCKTYPE_PCLK3; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK) { Error_Handler(); } } /** * @brief Power Configuration * @retval None */ static void SystemPower_Config(void) { HAL_PWREx_EnableVddIO2(); /* * Switch to SMPS regulator instead of LDO */ if (HAL_PWREx_ConfigSupply(PWR_SMPS_SUPPLY) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN PWR */ /* USER CODE END PWR */ } /* USER CODE BEGIN 4 */ void LED_PWM(uint16_t num) { if(num!=0) pwmstate = 1; else pwmstate = 0; switch(pwmstate) { case 0: if(0 == led0pwmval) break; else { HAL_Delay(5); led0pwmval--; __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,led0pwmval); } case 1: { HAL_Delay(5); if(dir)led0pwmval++; //dir==1 led0pwmval递增 else led0pwmval--; //dir==0 led0pwmval递减 if(led0pwmval>num)dir=0; //led0pwmval到达x00后,方向为减 if(led0pwmval<=0) dir=1; //led0pwmval递减x00后,方向为增 __HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,led0pwmval); } } } //按键上升沿触发中断返回函数 void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == USER_BUTTON_Pin) { HAL_Delay(50); HAL_GPIO_TogglePin(LED_BLUE_GPIO_Port,LED_BLUE_Pin); printf("key exti callback\r\n"); printf("Blue state is : %d\r\n",HAL_GPIO_ReadPin(LED_BLUE_GPIO_Port,LED_BLUE_Pin)); } } //输入捕获函数 void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { if(uhCaptureIndex == 0) { /* Get the 1st Input Capture value */ uwIC2Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); uhCaptureIndex = 1; } else if(uhCaptureIndex == 1) { /* Get the 2nd Input Capture value */ uwIC2Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1); /* Capture computation */ if (uwIC2Value2 > uwIC2Value1) { uwDiffCapture = (uwIC2Value2 - uwIC2Value1); } else if (uwIC2Value2 < uwIC2Value1) { /* 0xFFFF is max TIM1_CCRx value */ uwDiffCapture = ((0xFFFF - uwIC2Value1) + uwIC2Value2) + 1; } else { /* If capture values are equal, we have reached the limit of frequency measures */ Error_Handler(); } /* Frequency computation: for this example TIMx (TIM1) is clocked by APB2Clk */ uwFrequency = HAL_RCC_GetPCLK2Freq() / uwDiffCapture; uhCaptureIndex = 0; } } } //定时器6产生时基 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim == &htim6) { tim6_count++; } } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */     [localvideo]f8f0115d301f47c5687b8d0fb51aa92e[/localvideo]    

最近访客

< 1/6 >

统计信息

已有176人来访过

  • 芯积分:1854
  • 好友:1
  • 主题:52
  • 回复:116

留言

你需要登录后才可以留言 登录 | 注册


现在还没有留言