OLED屏幕改SSD1306 I2C接口:与EEPROM共用软件I2C总线(PB4/PB5,0x78),数据流式传输,storage_lock互斥;字库SPI不动;释放PC8/PC9/PA11
This commit is contained in:
parent
3cd34e6a2b
commit
1af245d43d
|
|
@ -63,7 +63,8 @@
|
|||
| NET_LED | **PB13**(LED2 仍 PC13) |
|
||||
| EEPROM I2C(SCL/SDA) | **PB5/PB4** |
|
||||
| W25Q64(CS/DO/CLK/DI) | **PB8/PB9/PB6/PB7** |
|
||||
| OLED(CS2/FSO/CS1/DC/MOSI/CLK/RES) | **PC12/PA12/PC8/PC9/PA15/PB3/PA11** |
|
||||
| OLED 屏幕 | **SSD1306 I2C:SCL=PB5/SDA=PB4(与 EEPROM 共总线,地址 0x78,无 RST)** |
|
||||
| 字库 IC(独立 SPI) | CLK=PB3 DI=PA15 FSO=PA12 CS2=PC12 |
|
||||
| HR_IN 缺料检测 | **PA8 下拉输入,高=缺料→停投料关继电器1(只记日志),不接传感器不影响投料** |
|
||||
| KEY1~4 | **PC6/PC7/PB14/PB15 上拉输入,功能预留** |
|
||||
| 取消 | PA8 手动模式开关(MANUAL_MODE 已删) |
|
||||
|
|
|
|||
|
|
@ -1,28 +1,23 @@
|
|||
/* oled.c - 128x64 OLED + 晶联讯 GB2312 字库 IC 驱动(GPIO 模拟 SPI)
|
||||
* 移植自《485模拟磅秤数据带CRC》工程 oledisp.c,引脚改为本板:
|
||||
* CLK=PB3 MOSI=PA15 DC=PC9 CS1=PC8 FSO=PA12 CS2=PC12 RST=PA11 */
|
||||
/* oled.c - 128x64 OLED(SSD1306, I2C) + 晶联讯 GB2312 字库 IC(SPI) 驱动
|
||||
* 屏幕: I2C 接口, 与 EEPROM 共用软件 I2C 总线(SCL=PB5 SDA=PB4), 无 RST 脚;
|
||||
* 与 24C02 的跨任务互斥用 storage_lock(每个完整显示事务内)
|
||||
* 字库: SPI 不变(CLK=PB3 DI=PA15 FSO=PA12 CS2=PC12) */
|
||||
|
||||
#include "oled.h"
|
||||
#include "qrcodegen.h"
|
||||
#include "iic.h"
|
||||
#include "app_loop.h" /* storage_lock/unlock */
|
||||
#include <string.h>
|
||||
|
||||
#define OLED_CLK_PORT GPIOB
|
||||
#define OLED_CLK_PIN GPIO_PIN_3
|
||||
#define OLED_MOSI_PORT GPIOA
|
||||
#define OLED_MOSI_PIN GPIO_PIN_15
|
||||
#define OLED_DC_PORT GPIOC
|
||||
#define OLED_DC_PIN GPIO_PIN_9
|
||||
#define OLED_CS1_PORT GPIOC
|
||||
#define OLED_CS1_PIN GPIO_PIN_8
|
||||
#define OLED_FSO_PORT GPIOA
|
||||
#define OLED_FSO_PIN GPIO_PIN_12
|
||||
#define OLED_CS2_PORT GPIOC
|
||||
#define OLED_CS2_PIN GPIO_PIN_12
|
||||
#define OLED_RST_PORT GPIOA
|
||||
#define OLED_RST_PIN GPIO_PIN_11 /* 复位脚,低电平复位(板内上拉,默认拉高即可) */
|
||||
|
||||
#define lcd_cs1(a) HAL_GPIO_WritePin(OLED_CS1_PORT, OLED_CS1_PIN, (GPIO_PinState)(a))
|
||||
#define lcd_dc(a) HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, (GPIO_PinState)(a))
|
||||
#define lcd_mosi(a) HAL_GPIO_WritePin(OLED_MOSI_PORT, OLED_MOSI_PIN, (GPIO_PinState)(a))
|
||||
#define lcd_clk(a) HAL_GPIO_WritePin(OLED_CLK_PORT, OLED_CLK_PIN, (GPIO_PinState)(a))
|
||||
#define rom_cs2(a) HAL_GPIO_WritePin(OLED_CS2_PORT, OLED_CS2_PIN, (GPIO_PinState)(a))
|
||||
|
|
@ -60,11 +55,10 @@ static void oled_gpio_init(void)
|
|||
__HAL_RCC_GPIOB_CLK_ENABLE();
|
||||
__HAL_RCC_GPIOC_CLK_ENABLE();
|
||||
|
||||
/* 先置好空闲电平再开推挽,避免毛刺 */
|
||||
/* 屏幕已改 I2C(不占 GPIO); 这里只初始化字库 IC 的 SPI 四线: CLK/DI/FSO/CS2
|
||||
* 先置好空闲电平再开推挽,避免毛刺 */
|
||||
HAL_GPIO_WritePin(OLED_CLK_PORT, OLED_CLK_PIN, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(OLED_MOSI_PORT, OLED_MOSI_PIN, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(OLED_DC_PORT, OLED_DC_PIN, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(OLED_CS1_PORT, OLED_CS1_PIN, GPIO_PIN_SET);
|
||||
HAL_GPIO_WritePin(OLED_CS2_PORT, OLED_CS2_PIN, GPIO_PIN_SET);
|
||||
|
||||
g.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
|
|
@ -73,35 +67,33 @@ static void oled_gpio_init(void)
|
|||
|
||||
g.Pin = OLED_CLK_PIN; HAL_GPIO_Init(OLED_CLK_PORT, &g);
|
||||
g.Pin = OLED_MOSI_PIN; HAL_GPIO_Init(OLED_MOSI_PORT, &g);
|
||||
g.Pin = OLED_DC_PIN; HAL_GPIO_Init(OLED_DC_PORT, &g);
|
||||
g.Pin = OLED_CS1_PIN; HAL_GPIO_Init(OLED_CS1_PORT, &g);
|
||||
g.Pin = OLED_CS2_PIN; HAL_GPIO_Init(OLED_CS2_PORT, &g);
|
||||
|
||||
/* RST(PA11):推挽输出,默认高(板内上拉,这里也主动拉高) */
|
||||
HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET);
|
||||
g.Pin = OLED_RST_PIN;
|
||||
g.Mode = GPIO_MODE_OUTPUT_PP;
|
||||
g.Pull = GPIO_NOPULL;
|
||||
g.Speed = GPIO_SPEED_FREQ_LOW;
|
||||
HAL_GPIO_Init(OLED_RST_PORT, &g);
|
||||
|
||||
fso_output();
|
||||
}
|
||||
|
||||
/*==== 写字节到屏幕(DC=0 指令 / DC=1 数据)====*/
|
||||
/*==== SSD1306 I2C 传输(与 EEPROM 共用软件 I2C 总线) ====*/
|
||||
#define OLED_I2C_ADDR 0x78 /* 8 位写地址(7 位 0x3C); 模块 SA0 拉高时为 0x7A */
|
||||
|
||||
/* 写字节到屏幕(dc=0 指令 / dc=1 数据): START+地址+控制字节+数据+STOP */
|
||||
static void oled_write(uint8_t dc, uint8_t dat)
|
||||
{
|
||||
lcd_dc(dc);
|
||||
lcd_cs1(0);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
lcd_clk(0);
|
||||
lcd_mosi(dat & 0x80);
|
||||
lcd_clk(1);
|
||||
dat <<= 1;
|
||||
iicStart();
|
||||
iicSendByteAck(OLED_I2C_ADDR);
|
||||
iicSendByteAck(dc ? 0x40 : 0x00);
|
||||
iicSendByteAck(dat);
|
||||
iicStop();
|
||||
}
|
||||
lcd_dc(1);
|
||||
lcd_cs1(1);
|
||||
|
||||
/* 数据流: 一次 START 连续写多字节(清屏/画图用, 比逐字节事务快约 3 倍) */
|
||||
static void oled_data_begin(void)
|
||||
{
|
||||
iicStart();
|
||||
iicSendByteAck(OLED_I2C_ADDR);
|
||||
iicSendByteAck(0x40);
|
||||
}
|
||||
static void oled_data_byte(uint8_t d) { iicSendByteAck(d); }
|
||||
static void oled_data_end(void) { iicStop(); }
|
||||
|
||||
/*==== 设置页/列地址 ====*/
|
||||
static void lcd_address(uint8_t page, uint8_t column)
|
||||
|
|
@ -159,15 +151,16 @@ void oled_show_qrcode(const char *text)
|
|||
}
|
||||
|
||||
/* 写左半屏 64 列(整页覆写, 不影响右侧文本区) */
|
||||
lcd_cs1(0);
|
||||
rom_cs2(1);
|
||||
storage_lock();
|
||||
for (uint8_t pg = 0; pg < 8; pg++) {
|
||||
oled_write(0, 0xb0 + pg);
|
||||
oled_write(0, 0x00);
|
||||
oled_write(0, 0x10);
|
||||
for (uint8_t x = 0; x < 64; x++) oled_write(1, pagebuf[pg][x]);
|
||||
oled_data_begin();
|
||||
for (uint8_t x = 0; x < 64; x++) oled_data_byte(pagebuf[pg][x]);
|
||||
oled_data_end();
|
||||
}
|
||||
lcd_cs1(1);
|
||||
storage_unlock();
|
||||
|
||||
/* 右侧 ID 文本: x=64 起每行 8 个 ASCII, 最多 3 行 */
|
||||
int len = (int)strlen(id);
|
||||
|
|
@ -185,35 +178,31 @@ void oled_show_qrcode(const char *text)
|
|||
/*==== 关显示(黑屏,断电预警时调用)====*/
|
||||
void oled_off(void)
|
||||
{
|
||||
storage_lock();
|
||||
oled_write(0, 0xAE); /* display off */
|
||||
storage_unlock();
|
||||
}
|
||||
|
||||
/*==== 全屏清屏 ====*/
|
||||
void oled_clear(void)
|
||||
{
|
||||
lcd_cs1(0);
|
||||
rom_cs2(1);
|
||||
storage_lock();
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
oled_write(0, 0xb0 + i);
|
||||
oled_write(0, 0x00);
|
||||
oled_write(0, 0x10);
|
||||
for (uint8_t j = 0; j < 128; j++) oled_write(1, 0x00);
|
||||
oled_data_begin();
|
||||
for (uint8_t j = 0; j < 128; j++) oled_data_byte(0x00);
|
||||
oled_data_end();
|
||||
}
|
||||
lcd_cs1(1);
|
||||
storage_unlock();
|
||||
}
|
||||
|
||||
/*==== 屏幕初始化(SSD1306 兼容序列)====*/
|
||||
void oled_init(void)
|
||||
{
|
||||
HAL_Delay(400); /* 等屏幕/字库上电稳定 */
|
||||
HAL_Delay(400); /* 等屏幕/字库上电稳定(I2C 屏无 RST 脚, 靠上电延时) */
|
||||
oled_gpio_init();
|
||||
|
||||
/* 硬件复位一次屏幕(RST 低 10ms),保证从确定状态开始初始化 */
|
||||
HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_RESET);
|
||||
HAL_Delay(10);
|
||||
HAL_GPIO_WritePin(OLED_RST_PORT, OLED_RST_PIN, GPIO_PIN_SET);
|
||||
HAL_Delay(120);
|
||||
lcd_cs1(0);
|
||||
rom_cs2(1);
|
||||
oled_write(0, 0xAE); /* display off */
|
||||
oled_write(0, 0x20); /* 寻址模式 */
|
||||
|
|
@ -243,33 +232,35 @@ void oled_init(void)
|
|||
oled_write(0, 0x8d); /* DC-DC */
|
||||
oled_write(0, 0x14);
|
||||
oled_write(0, 0xaf); /* display on */
|
||||
lcd_cs1(1);
|
||||
oled_clear();
|
||||
}
|
||||
|
||||
/*==== 显示 16x16 点阵(汉字)====*/
|
||||
static void display_graphic_16x16(uint8_t page, uint8_t column, const uint8_t *dp)
|
||||
{
|
||||
lcd_cs1(0);
|
||||
rom_cs2(1);
|
||||
storage_lock();
|
||||
for (uint8_t j = 2; j > 0; j--) {
|
||||
lcd_address(column, page);
|
||||
for (uint8_t i = 0; i < 16; i++) oled_write(1, *dp++);
|
||||
oled_data_begin();
|
||||
for (uint8_t i = 0; i < 16; i++) oled_data_byte(*dp++);
|
||||
oled_data_end();
|
||||
page++;
|
||||
}
|
||||
lcd_cs1(1);
|
||||
storage_unlock();
|
||||
}
|
||||
|
||||
/*==== 显示 8x16 点阵(ASCII)====*/
|
||||
static void display_graphic_8x16(uint8_t page, uint8_t column, const uint8_t *dp)
|
||||
{
|
||||
lcd_cs1(0);
|
||||
storage_lock();
|
||||
for (uint8_t j = 2; j > 0; j--) {
|
||||
lcd_address(column, page);
|
||||
for (uint8_t i = 0; i < 8; i++) oled_write(1, *dp++);
|
||||
oled_data_begin();
|
||||
for (uint8_t i = 0; i < 8; i++) oled_data_byte(*dp++);
|
||||
oled_data_end();
|
||||
page++;
|
||||
}
|
||||
lcd_cs1(1);
|
||||
storage_unlock();
|
||||
}
|
||||
|
||||
/*==== 字库 IC 写字节(指令/地址)====*/
|
||||
|
|
@ -303,7 +294,6 @@ static uint8_t rom_read_byte(void)
|
|||
static void rom_read_n(uint8_t ah, uint8_t am, uint8_t al, uint8_t *buf, uint8_t len)
|
||||
{
|
||||
rom_cs2(0);
|
||||
lcd_cs1(1);
|
||||
lcd_clk(0);
|
||||
rom_write_byte(0x03); /* 读指令 */
|
||||
rom_write_byte(ah);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
#include "main.h"
|
||||
|
||||
/* 128x64 OLED(SSD1306 兼容指令)+ 晶联讯 GB2312 字库 IC,全部 GPIO 模拟 SPI。
|
||||
* 接线(V1.7.0 新板):CLK=PB3 MOSI=PA15 DC=PC9 CS1=PC8(屏幕片选) FSO=PA12(字库数据,读MCU方向)
|
||||
* CS2=PC12(字库片选) RST=PA11
|
||||
* ÆÁÄ»: SSD1306 I2C(SCL=PB5 SDA=PB4, Óë EEPROM ¹²×ÜÏß, ÎÞ RST)
|
||||
* ×Ö¿â: SPI(CLK=PB3 DI=PA15 FSO=PA12 CS2=PC12)
|
||||
* 显示字符串必须是 GB2312/GBK 编码(本工程源文件即 GBK,直接写中文字面量即可)。
|
||||
* 屏幕 128x64:16 像素高的行共 4 行(row 0~3),每行 8 个汉字或 16 个 ASCII。 */
|
||||
|
||||
|
|
|
|||
4
版本说明.md
4
版本说明.md
|
|
@ -21,6 +21,10 @@
|
|||
控制命令改三段式:FC03 预读(判定在线 + 快照命令前反馈)→ FC05 → 150ms → FC03 校验跳变;
|
||||
命令链路最终无应答即判离线并应答平台 `ext relay board offline`,下次命令自动重新探测恢复;
|
||||
断电恢复触发点不变(离线→上线比对 EEPROM 逐路补发)
|
||||
- **OLED 屏幕改 I2C 接口**(SSD1306 I2C 版,无 RST 脚):与 EEPROM 共用软件 I2C 总线(SCL=PB5/SDA=PB4,
|
||||
地址 0x78);显示数据流式传输(一次 START 连续写,比逐字节事务快约 3 倍);与 24C02 的跨任务互斥
|
||||
用 storage_lock 包每个完整显示事务;字库 IC 仍为独立 SPI(CLK=PB3/DI=PA15/FSO=PA12/CS2=PC12,暂不动);
|
||||
释放 IO:PC8(CS1)、PC9(DC)、PA11(RST) 共 3 个(后续字库并入 Flash SPI 可再省 2 个)
|
||||
- **联网方式改为开机按键手动选择**(废除自动切换):欢迎页后 10s 倒计时,KEY1(PC6)=4G /
|
||||
KEY2(PC7)=WiFi 固定热点 / KEY3(PB14)=SmartConfig 配网;倒计时内按不同键**可反复切换选中项**,
|
||||
**重复按当前项=立即确认**,超时=当前选中项生效;初始选中项=EEPROM 记忆的上次选择(首次默认 4G);
|
||||
|
|
|
|||
Loading…
Reference in New Issue