爱易族 - 编程
type: channel
link: http://www.yizu.org/category/bcxg
items: GT20L16S1Y字库芯片的Arduino示例代码
items: Arduino用Wire库驱动SS1306 OLED显示屏（I2C）
items: linux命令行安装golang
items: 解决'go get' is no longer supported outside a module.问题
items: 基于arduboy_homemade自制Arduboy的一些说明
items: Android Studio Giraffe | 2022.3.1版本解决创建项目下载gradle缓慢问题
items: STC8G1K08A+DS18B20测温系统
items: 51单片机（stc15f104w）驱动oled显示模块（ssd1306）
items: VSCode+EIDE+SDCC进行51单片机开发
items: c#读取word文档（NPOI）

GT20L16S1Y字库芯片的Arduino示例代码
type: item
date: 2026-02-09T22:27:00+08:00
description: GT20L16S1Y字库芯片比较常用，现把调试通过的Arduino代码记录一下。以下代码需使用U8G2图形库。接线方面字库芯片和LCD屏共用SPI接口，以CS引脚区分数据传输。#include <Arduino.h> #include <U8g2lib.h> #include <SPI.h> // --- 硬件定义 --- #define PIN_LCD_CS 7 #define PIN_LCD_DC 6 #define PIN_LCD_RST 11 #define PIN_FONT_CS 5 // --- U8g2 初始化 --- // 你的屏幕构造函数 U8G2_ST7565_NHD_C12864_1_4W_HW_SPI u8g2(U8G2_R0, PIN_LCD_CS, PIN_LCD_DC, PIN_LCD_RST); // 汉字点阵缓冲区 (16x16点阵 = 32字节) uint8_t fontBuffer[32]; // 英文字符点阵缓冲8*16 uint8_t asciiBuffer[16]; void setup() { // 初始化串口 (调试用) Serial.begin(115200); // 初始化字库芯片引脚 pinMode(PIN_FONT_CS, OUTPUT); digitalWrite(PIN_FONT_CS, HIGH); // 默认拉高，取消选中 // 初始化 SPI SPI.begin(); // 初始化屏幕 u8g2.begin(); } // 从GT20L16S1Y读取16x16汉字点阵数据 void readFontData(uint8_t msb, uint8_t lsb, uint8_t *buffer) { unsigned long address; // GT20L16S1Y GB2312 地址计算公式： // BaseAddr + ((MSB - 0xB0) * 94 + (LSB - 0xA1)) * 32 if (msb >= 0xA1 && msb <= 0xA3 && lsb >= 0xA1) { address = ((unsigned long)(msb - 0xA1) * 94 + (lsb - 0xA1)) * 32; } else if (msb >= 0xB0 && msb <= 0xF7 && lsb >= 0xA1) { address = ((unsigned long)(msb - 0xB0) * 94 + (lsb - 0xA1) + 846) * 32; } else if (msb == 0xA9 && lsb >= 0xA1) { address = (282 + (lsb - 0xA1)) * 32; } else { address = 0; } // 开始SPI事务读取字库 SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); // GT20L16S1Y支持高达30MHz+ digitalWrite(PIN_FONT_CS, LOW); // 发送读取命令 0x03 SPI.transfer(0x03); // 发送地址 (24位地址，高位在前) SPI.transfer((address >> 16) & 0xFF); SPI.transfer((address >> 8) & 0xFF); SPI.transfer(address & 0xFF); // 读取32个字节的点阵数据 for (int i = 0; i < 32; i++) { buffer[i] = SPI.transfer(0x00); } digitalWrite(PIN_FONT_CS, HIGH); SPI.endTransaction(); } // 从GT20L16S1Y读取ASCII8x16点阵数据 void readASCIIData(uint8_t asciichar, uint8_t *buffer) { unsigned long address = (asciichar-0x20)*16 + 0x3cf80; // 开始SPI事务读取字库 SPI.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE0)); // GT20L16S1Y支持高达30MHz+ digitalWrite(PIN_FONT_CS, LOW); // 发送读取命令 0x03 SPI.transfer(0x03); // 发送地址 (24位地址，高位在前) SPI.transfer((address >> 16) & 0xFF);…

Arduino用Wire库驱动SS1306 OLED显示屏（I2C）
type: item
date: 2024-11-15T20:46:18+08:00
description: 很基础的一段代码，用的硬件I2C，记录一下方便使用。#include <Wire.h> #include <avr/pgmspace.h> #define I2CADDR 0x3c // 显示屏I2C地址7位 #define WIRE_MAX 32 //WIRE一次最大发送字节数 const uint8_t display_init_sequence[] PROGMEM = { // Initialization Sequence 0xAE, // Display OFF (sleep mode) 0x20, 0x02, // Set Memory Addressing Mode // 00=Horizontal Addressing Mode; 01=Vertical Addressing Mode; // 10=Page Addressing Mode (RESET); 11=Invalid 0xB0, // Set Page Start Address for Page Addressing Mode, 0-7 0xC8, // Set COM Output Scan Direction 0x00, // ---set low column address display:0x00 sh1106:0x02 0x10, // ---set high column address 0x40, // --set start line address 0x81, 0x3F, // Set contrast control register 0xA1, // Set Segment Re-map. A0=address mapped; A1=address 127 mapped. 0xA6, // Set display mode. A6=Normal; A7=Inverse 0xA8, 0x3F, // Set multiplex ratio(1 to 64) 0xA4, // Output RAM to Display // 0xA4=Output follows RAM content; 0xA5,Output ignores RAM content 0xD3, 0x00, // Set display offset. 00 = no offset 0xD5, // --set display clock divide ratio/oscillator frequency 0xF0, // --set divide ratio 0xD9, 0x22, // Set pre-charge period 0xDA, 0x12, // Set com pins hardware configuration 0xDB, // --set vcomh 0x20, // 0x20,0.77xVcc 0x8D, 0x14, // Set DC-DC enable 0xAF // Display ON in normal mode }; /* Standard ASCII 6x8 font */ const uint8_t display_font6x8 [] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sp 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00, // ! 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, // " 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14, // # 0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12, // $ 0x00, 0x62, 0x64, 0x08, 0x13, 0x23, // % 0x00, 0x36, 0x49, 0x55, 0x22, 0x50, // & 0x00, 0x00, 0x05, 0x03, 0x00, 0x00, // ' 0x00, 0x00, 0x1c, 0x22, 0x41, 0x00, // ( 0x00, 0x00, 0x41, 0x22, 0x1c, 0x00, // ) 0x00, 0x14, 0x08, 0x3E, 0x08, 0x14, // * 0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, // + 0x00, 0x00, 0x00, 0xA0, 0x60, 0x00, // , 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, // - 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, // . 0x00, 0x20, 0x10, 0x08, …

linux命令行安装golang
type: item
date: 2024-03-21T21:08:14+08:00
description: 首先下载golang安装包，版本号根据需要修改。wget https://dl.google.com/go/go1.22.1.linux-amd64.tar.gz sudo tar -C /usr/local -xzf go1.22.1.linux-amd64.tar.gz 设置环境变量，并生效。echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bash_profile echo 'export GOPATH=$HOME/go' >> ~/.bash_profile source ~/.bash_profile 检查安装成功与否go version 安装好了就可以在go项目目录下运行go get下载依赖，运行go build编译。

解决'go get' is no longer supported outside a module.问题
type: item
date: 2024-03-10T20:13:00+08:00
description: 执行go get命令，提示：go: go.mod file not found in current directory or any parent directory. 'go get' is no longer supported outside a module. To build and install a command, use 'go install' with a version, like 'go install example.com/cmd@latest' For more information, see https://golang.org/doc/go-get-install-deprecation or run 'go help get' or 'go help install'.这个错误提示说明当前目录或其父目录中都找不到 go.mod 文件，而且在 Go 1.16 版本之后，使用 go get 命令在没有模块的情况下是不再支持的。要解决这个问题，你可以按照以下步骤进行操作：确保你的工作目录是正确的。进入你的项目根目录，或者创建一个新的模块。如果你已经有了 go.mod 文件，请确认它是否存在于正确的位置，并且文件名为 “go.mod”。如果你还没有创建 go.mod 文件，则需要通过运行 go mod init 命令来初始化一个新模块：go mod init <module-name> 这将会在当前目录下生成一个新的 go.mod 文件，并设置模块名称为 <module-name>。完成上述步骤后，应该就能够成功运行 go get 或其他相关命令了。如果问题仍然存在，请确保你安装了最新版本的 Go 并且环境配置正确。

基于arduboy_homemade自制Arduboy的一些说明
type: item
date: 2023-11-17T21:30:00+08:00
description: 自制Arduboy有一个包arduboy_homemade可以简化我们arduino配置工作，并扩展了不少功能。地址如下https://github.com/MrBlinky/Arduboy-homemade-package。安装这个包只要在Arduino IDE文件->首选项,把https://raw.githubusercontent.com/MrBlinky/Arduboy-homemade-package/master/package_arduboy_homemade_index.json 添加到“其它开发板管理器地址”。然后在开发板管理中下载包即可，当然也可以在github下载zip包后离线添加。在github主页，有一个表格Pin wiring table，里面详细说明了引脚链接,为使用方便，直接复制在这儿。Arduboy functionArduboy Leonardo/MicroDevelopmentKitProMicro 5V (standard wiring)ProMicro 5V (alternate wiring)OLED CS12 PORTD66 PORTD7GND/(inverted CART_CS)**1/TXO PORTD3*OLED DC4 PORTD44 PORTD44 PORTD44 PORTD4OLED RST6 PORTD712 PORTD66 PORTD72 PORTD1*SPI SCK15 PORTB115 PORTB115 PORTB 115 PORTB1SPI MOSI16 PORTB216 PORTB216 PORTB216 PORTB2RGB LED RED10 PORTB6_10 PORTB610 PORTB6RGB LED GREEN11 PORTB7_-3 PORTD0*RGB LED BLUE9 PORTB517 PORTB09 PORTB59 PORTB5RxLED17 PORTB0_17 PORTB017 PORTB0TxLED30 PORTD5_30 PORTD530 PORTD5BUTTON UPA0 PORTF78 PORTB4A0 PORTF7A0 PORTF7BUTTON RIGHTA1 PORTF65 PORTC6A1 PORTF6A1 PORTF6BUTTON LEFTA2 PORTF59 PORTB5A2 PORTF5A2 PORTF5BUTTON DOWNA3 PORTF410 PORTB6A3 PORTF4A3 PORTF4BUTTON A (left)7 PORTE6A0 PORTF77 PORTE67 PORTE6BUTTON B (right)8 PORTB4A1 PORTF68 PORTB48 PORTB4SPEAKER PIN 15 PORTC6A2 PORTF55 PORTC65 PORTC6SPEAKER PIN 213 PORTC7A3 PORTF4**GND6 PORTD7*CART_CS (org)0 PORTD2*-0 PORTD2*0 PORTD2*CART_CS (new)2 PORTD1*-2 PORTD1*-SPI MISO14 PORTB3*--14 PORTB3*OLED SDA4 PORTD4*-4 PORTD4*4 PORTD4*OLED SCL6 PORTD7*-6 PORTD7*1/TXO PORTD3*安装完arduboy_homemade之后，把开发板设置为homemade Arduboy,自制Arduboy最简单的就是使用Arduino Pro micro这个板子。在开发板设置里面可以设置为如下图所示。Based on里面有两个关于Pro micro的选项。一个是标准接线，一个是备用接线，分别对应上面表格里面最右边两列，按照表格接线即可。Bootloader选项，选择Cathy3K(start with menu),可以支持外挂Flash芯片，上传游戏合集包。Display选择SSD1306是兼容性最强的，这样设置烧录的Bootloader可以直接使用编译好的游戏和游戏合集包，使用Arduboy-uploader这个工具上传即可。而使用其它的显示屏则只能使用Arduino IDE编译游戏源码上传游戏。我这里测试SH1103 IIC支持不好，画面抖动厉害。Flash select这个选项是专门针对外挂Flash芯片的，就是在PD2（RX1）和PD1（2）中选择一个作为SPIFlash的片选（CS）引脚，不外挂Flash可以不用理它。使用外挂Flash芯片还有一个要注意的是，我们SPI显示屏的SCL和SDA是和Flash芯片共用的，这个时候显示屏的CS引脚接地（始终激活）就行不通了，表现为在游戏菜单…

Android Studio Giraffe | 2022.3.1版本解决创建项目下载gradle缓慢问题
type: item
date: 2023-09-24T10:40:57+08:00
description: 新版本Android Studio的maven写法改变了，所以网上的老版本的修改gradle下载源的方法都无效了，改完会报错Unexpected tokens (use ';' to separate expressions on the same line)。新的版本方法如下。找到如下所示settings.gradle.kts。打开后在两个地方添加如下代码 maven { url =uri("https://plugins.gradle.org/m2/")} maven { url =uri("https://maven.aliyun.com/nexus/content/repositories/google")} maven { url =uri("https://maven.aliyun.com/nexus/content/groups/public") } maven { url =uri("https://maven.aliyun.com/nexus/content/repositories/jcenter")}改完后这样。pluginManagement { repositories { maven { url =uri("https://plugins.gradle.org/m2/")} maven { url =uri("https://maven.aliyun.com/nexus/content/repositories/google")} maven { url =uri("https://maven.aliyun.com/nexus/content/groups/public") } maven { url =uri("https://maven.aliyun.com/nexus/content/repositories/jcenter")} google() mavenCentral() gradlePluginPortal() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { maven { url =uri("https://plugins.gradle.org/m2/")} maven { url =uri("https://maven.aliyun.com/nexus/content/repositories/google")} maven { url =uri("https://maven.aliyun.com/nexus/content/groups/public") } maven { url =uri("https://maven.aliyun.com/nexus/content/repositories/jcenter")} google() mavenCentral() } } rootProject.name = "My Application" include(":app")

STC8G1K08A+DS18B20测温系统
type: item
date: 2022-07-31T19:14:00+08:00
description: 关于驱动DS18B20，关键是时序，延时要准确，随便网上抄了个代码（https://blog.csdn.net/Ele_PPP/article/details/88712895），改了下撸了一个温度计。之前1个STC8G1K08A片子有问题，搞了好几天没成，换了一个片子立马好了。又撸了一个外壳，看起来有点像样了。外观如下。代码是11.0592MHz时钟频率下的，屏幕采用0.91寸OLED，分辨率128*32。Keil C51编译。main.c#include <STC8G.H> #include <intrins.h> #include "oled.h" #include "stdio.h" #include "string.h" sbit DS18B20_DQ = P5^4; //DS18B20 IO设置 unsigned char flag_temper = 0; //定义变量 void Delay_1ms(unsigned int ms); unsigned int Get_temp(void); void main() { unsigned int temp; char str[10]; unsigned int temp1; unsigned int temp2; unsigned int theLocation; P3M0=0; P3M1=0; P5M0=0; P5M1=0; OLED_Init(); //初始化OLED OLED_Clear(); OLED_On(); Delay_1ms(2000); OLED_Clear(); Delay_1ms(1000); while (1) { OLED_ShowCHinese(0, 0, 0); //温 OLED_ShowCHinese(16, 0, 1); //度 OLED_ShowCHinese(32, 0, 2); //计 //OLED_ShowString(56, 0, "YIZU.ORG"); temp = Get_temp(); temp1=temp/10; temp2=temp-temp1*10; if(flag_temper==1){ sprintf(str, "Temp:-%d.%d", temp1,temp2); } else{ sprintf(str, "Temp:%d.%d", temp1,temp2); } OLED_ShowString(0, 2, str); theLocation=strlen(str)*8; OLED_ShowCHinese(theLocation+2, 2, 3); //℃ Delay_1ms(500); } } //**************************************************** //DS18B20延时函数 //**************************************************** void delay2us(void) { unsigned char i; _nop_(); i = 5; while (--i); } void delay10us(void) { unsigned char i; i = 35; while (--i); } void delay60us(void) { unsigned char i; _nop_(); i = 219; while (--i); } void delay500us(void) { unsigned char i, j; _nop_(); _nop_(); i = 8; j = 43; do { while (--j); } while (--i); } void Delay_1ms(unsigned int ms) //@11.0592MHz { unsigned char i, j; while (--ms) { _nop_(); i = 11; j = 190; do { while (--j) ; } while (--i); } } //**************************************************** //DS18B20初始化 //**************************************************** bit DS18B20_Init() { bit Flag_exist = 1; //初始化结果标志 DS18B20_DQ = 1; //单片机管脚电平拉高，以释放总线 delay2us(); //延时>1us，执行2us DS18B20_DQ = 0; //单片机电平拉低以启动DS18B20初始化 delay5…

51单片机（stc15f104w）驱动oled显示模块（ssd1306）
type: item
date: 2022-07-10T21:37:00+08:00
description: 这里采用stc15f104w单片机，8脚，换其它51单片机也适用。本文代码修改自https://gitee.com/oldzhai/stc89c51/，因为这个单片机内存资源较少，精简了不少内容，并且移植到了SDCC编译器编译。mian.c//以下代码用SDCC编译 #include<8052.h> #include "oled.h" void main() { OLED_Init(); //初始化OLED OLED_Clear(); Delay_1ms(2000); while (1) { OLED_ShowCHinese(0, 0, 0); //爱 OLED_ShowCHinese(16, 0, 1); //易 OLED_ShowCHinese(32, 0, 2); //族 OLED_ShowString(0, 3, "www.yizu.org", 16); Delay_1ms(2000); } }oled.h#include <8052.h> #define u8 unsigned char #define u32 unsigned int #define OLED_CMD 0 //写命令 #define OLED_DATA 1 //写数据 //I2C管脚定义 #define OLED_SCL P3_3 //SCL #define OLED_SDIN P3_2 //SDA #define OLED_SCLK_Clr() OLED_SCL=0 #define OLED_SCLK_Set() OLED_SCL=1 #define OLED_SDIN_Clr() OLED_SDIN=0 #define OLED_SDIN_Set() OLED_SDIN=1 #define Max_Column 128 #define Max_Row 64 //-----------------延时函数---------------- void Delay_50ms(unsigned int Del_50ms); void Delay_1ms(unsigned int Del_1ms); //OLED控制用函数 void OLED_WR_Byte(unsigned dat,unsigned cmd); void OLED_Display_On(void); void OLED_Display_Off(void); void OLED_Init(void); void OLED_Clear(void); void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot); void OLED_ShowChar(u8 x,u8 y,u8 chr,u8 Char_Size); void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size); void OLED_ShowString(u8 x,u8 y, u8 *p,u8 Char_Size); void OLED_Set_Pos(unsigned char x, unsigned char y); void OLED_ShowCHinese(u8 x,u8 y,u8 no); void IIC_Start(); void IIC_Stop(); void Write_IIC_Command(unsigned char IIC_Command); void Write_IIC_Data(unsigned char IIC_Data); void Write_IIC_Byte(unsigned char IIC_Byte); void IIC_Wait_Ack();oled.c#include "oled.h" #include "font.h" /***********************Delay****************************************/ void Delay_50ms(unsigned int Del_50ms) { unsigned int m; for(;Del_50ms>0;Del_50ms--) for(m=6245;m>0;m--); } void Delay_1ms(unsigned int Del_1ms) { unsigned char j; while(Del_1ms--) { for(j=0;j<123;j++); } } /********************************************** //IIC Start **********************************************/ void IIC_Start() …

VSCode+EIDE+SDCC进行51单片机开发
type: item
date: 2022-07-08T19:27:58+08:00
description: 由于Keil收费，想要免费的替代，SDCC是51单片机开发不错的选择。这里用VSCode、EIDE和SDCC编译器组合来进行51单片机开发。1.首先安装SDCC编译器，SDCC的特点是免费、开源和跨平台，下载地址：https://sourceforge.net/projects/sdcc/files/。2.安装VSCode和EIDE，在VSCode扩展里面找到Embedded IDE并安装。3.设置EIDE，一般情况下在安装好SDCC后安装EIDE，工具链路径已经默认设置为SDCC，如果没设置好就手动设置一下。4.开始开发，打开EIDE，新建项目，选择模板，可以选择现成的模板，比如内置项目模板和从远程仓库获取里面都有针对51单片机的专门模板（带SDCC Toolchain或者with sdcc compiler的），当然也可以选择空项目->8位MCU项目，键入项目名称，选择项目保存位置，切换工作区，点左侧构建配置：SDCC->构建器选项->全局选项，在下面的编译器附加选项（全局）里面填入：--iram-size 128 --xram-size 0 --code-size 4096，这段设置对应的是STC15F104W单片机，其它单片机自行修改，然后点右上全部保存。这样就设置好了，可以开发了。--iram-size 128 --xram-size 0 --code-size 4096 \\参数说明 iram-size 用来检查片内ram的使用情况 xram-size 用来检查外部ram的使用情况 code-size 用来检查rom的使用情况 stack-size 用来检查堆栈的使用情况5.SDCC和Keil在语法上还是有一些区别的。1.sbit keil C： sbit SDA = P1 ^ 5; sbit CLK_ST = P1 ^ 6; SDCC: #define SDA P1_5 #define CLK_ST P1_6 2.中断 在sdcc中，中断处理函数使用关键字__interrupt标识，后面跟上中断号 keil C： void SerialComm() interrupt 4 SDCC: void SerialComm() __interrupt 4 3._nop_() 在sdcc中，没有_nop_()，可以用 #define _nop_() __asm NOP __endasm 替代 SDCC: #define _nop_() __asm NOP __endasm

c#读取word文档（NPOI）
type: item
date: 2022-07-06T09:29:16+08:00
description: 添加引用ICSharpCode.SharpZipLib.dll、NPOI.dll、NPOI.OOXML.dll、NPOI.OpenXml4Net.dll、NPOI.OpenXmlFormats.dll，这几个dll文件NPOI官网上只能下载到源码，编译有些麻烦。这里找到一个现成的，http://www.itmop.com/downinfo/267826.html。源码如下。using System; using System.Collections.Generic; using System.Windows.Forms; using NPOI.XWPF.UserModel; using System.IO; namespace WindowsFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { openFileDialog1.Title = "选择word文件"; openFileDialog1.Filter = "Word文档|*.docx"; if (openFileDialog1.ShowDialog() == DialogResult.OK) { textBox1.Text = openFileDialog1.FileName; } } private void button2_Click(object sender, EventArgs e) { //遍历word文档所有段落，并存入文本文件 FileStream fs = new FileStream(textBox1.Text, FileMode.Open); XWPFDocument doc = new XWPFDocument(fs); IList<XWPFParagraph> paragraphs = doc.Paragraphs; foreach(XWPFParagraph paragraph in paragraphs) { File.AppendAllText("⽂本1.txt", paragraph.Text); } } } }