482 lines
12 KiB
C
482 lines
12 KiB
C
/* USER CODE BEGIN Header */
|
||
/**
|
||
******************************************************************************
|
||
* @file ht16k33_led_i2c.c
|
||
* @author Motor Control SDK Team, Yuwell Software XiangenWang
|
||
* @brief Voice Recognition Module Initialization Section,
|
||
including peripheral initialization and message node insertion, etc.
|
||
* @version 1.0
|
||
* @changelog version 1.0 初始版本 2025.12.17
|
||
- 新增:新建第一个版本的软件,待完善解析命令后的程序执行部分
|
||
******************************************************************************
|
||
* @attention
|
||
*
|
||
* <h2><center>© Copyright (c) 2025 Yuwell Software Danyang.Jiangsu.China.
|
||
* All rights reserved.</center></h2>
|
||
*
|
||
* Redistribution and use in source and binary forms, with or without
|
||
* modification, are permitted, provided that the following conditions are met:
|
||
*
|
||
* 1. Redistribution of source code must retain the above copyright notice,
|
||
* this list of conditions and the following disclaimer.
|
||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||
* this list of conditions and the following disclaimer in the documentation
|
||
* and/or other materials provided with the distribution.
|
||
* 3. Neither the name of Yuwell Software nor the names of other
|
||
* contributors to this software may be used to endorse or promote products
|
||
* derived from this software without specific written permission.
|
||
* 4. This software, including modifications and/or derivative works of this
|
||
* software, must execute solely and exclusively on microcontroller or
|
||
* microprocessor devices manufactured by or for Yuwell Software.
|
||
* 5. Redistribution and use of this software other than as permitted under
|
||
* this license is void and will automatically terminate your rights under
|
||
* this license.
|
||
*
|
||
* THIS SOFTWARE IS PROVIDED BY Yuwell Software AND CONTRIBUTORS "AS IS"
|
||
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
|
||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
|
||
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
|
||
* SHALL Yuwell Software OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
*
|
||
******************************************************************************
|
||
*/
|
||
/* USER CODE END Header */
|
||
#include "ht16k33_dot_matrix.h"
|
||
|
||
|
||
|
||
#define SDA_SET HT16K33_SDA_SET
|
||
#define SCL_SET HT16K33_SCL_SET
|
||
|
||
#define SDA_CLEAR HT16K33_SDA_CLEAR
|
||
#define SCL_CLEAR HT16K33_SCL_CLEAR
|
||
|
||
|
||
/* 八行显示内存 */
|
||
uint8_t ht16k33_disp_buff[DISP_BUFFER_SIZE];
|
||
|
||
|
||
|
||
/**
|
||
* @brief 微秒延时
|
||
* @param us 需要延时的微秒数
|
||
* @retval NONE
|
||
* @note 根据MCU主频调整,确保时序满足HT16K33要求
|
||
* @author jarvis
|
||
* @data 2025.11.25
|
||
*/
|
||
void I2C_Delay_us(uint32_t us)
|
||
{
|
||
FL_DelayUs(us);
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief I2C起始条件:SCL高电平时,SDA从高变低
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note 根据飞利浦I2C官方文档编写
|
||
* @author jarvis
|
||
* @data 2025.11.25
|
||
*/
|
||
void I2C_Start(void)
|
||
{
|
||
SDA_SET();
|
||
SCL_SET();
|
||
I2C_Delay_us(1);
|
||
SDA_CLEAR();
|
||
I2C_Delay_us(1);
|
||
SCL_CLEAR();
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief I2C停止条件:SCL高电平时,SDA从低变高
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note 根据飞利浦I2C官方文档编写,停止后释放I2C总线控制权
|
||
* @author jarvis
|
||
* @date 2025.11.25
|
||
*/
|
||
static void I2C_Stop(void)
|
||
{
|
||
SDA_CLEAR();
|
||
SCL_SET();
|
||
I2C_Delay_us(1);
|
||
SDA_SET();
|
||
I2C_Delay_us(1);
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief I2C接收应答信号
|
||
* @param NONE
|
||
* @retval uint8_t - 应答检测结果:0表示接收到应答(ACK),1表示未接收到应答(NACK)
|
||
* @note SDA引脚需配置为输入模式,通过检测PC11引脚电平判断应答状态,遵循I2C协议时序
|
||
* @author jarvis
|
||
* @date 2025.11.25
|
||
*/
|
||
static uint8_t I2C_ReceiveAck(void)
|
||
{
|
||
|
||
uint8_t ack = 1;
|
||
SCL_CLEAR();
|
||
SDA_SET(); // 释放SDA总线
|
||
I2C_Delay_us(1);
|
||
SCL_SET();
|
||
I2C_Delay_us(1);
|
||
|
||
|
||
if((FL_GPIO_ReadInputPort(HT16K33_SDA_GPIO_GROUP)&HT16K33_SDA_GPIO_PIN) == 0)
|
||
{
|
||
ack = 0; // 检测到应答
|
||
}
|
||
SCL_CLEAR();
|
||
|
||
return ack;
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief I2C发送一个字节数据
|
||
* @param data - 待发送的8位数据
|
||
* @retval NONE
|
||
* @note 高位先行(MSB first),遵循I2C协议时序,SCL高电平时数据有效
|
||
* @author jarvis
|
||
* @date 2025.11.25
|
||
*/
|
||
static void I2C_SendByte(uint8_t data)
|
||
{
|
||
uint8_t i;
|
||
SCL_CLEAR();
|
||
for(i = 0; i < 8; i++)
|
||
{
|
||
if(data & 0x80)
|
||
{
|
||
SDA_SET(); // 发送最高位
|
||
}else{
|
||
SDA_CLEAR();
|
||
}
|
||
data <<= 1;
|
||
I2C_Delay_us(1);
|
||
SCL_SET();
|
||
I2C_Delay_us(1);
|
||
SCL_CLEAR();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 将显存数据下发到HT16K33驱动的屏幕
|
||
* @param disp_buffer - 显存数据缓冲区指针,存储待显示的字节数据
|
||
* @retval uint8_t - 发送结果:0表示发送成功,1表示发送失败(未收到应答)
|
||
* @note 采用I2C页写模式,地址自动递增;需提前定义HT16K33_ADDR(设备地址)、HT16K33_CMD_DISP_ADDR(显示起始地址)、DISP_BUFFER_SIZE(显存大小)
|
||
* @author jarvis
|
||
* @date 2025.11.25
|
||
*/
|
||
uint8_t ht16k33_send_buffer(uint8_t* disp_buffer)
|
||
{
|
||
uint8_t i;
|
||
|
||
// 1.发送起始信号
|
||
I2C_Start();
|
||
|
||
// 2.发送下位机地址
|
||
I2C_SendByte(HT16K33_ADDR);
|
||
|
||
// 3.接受应答信号
|
||
if(I2C_ReceiveAck() != 0)
|
||
{
|
||
I2C_Stop();
|
||
return 1;
|
||
}
|
||
|
||
// 4.发送地址数据
|
||
I2C_SendByte(HT16K33_CMD_DISP_ADDR); // 起始地址0x00,自动递增
|
||
|
||
|
||
// 5.接受应答信号
|
||
if(I2C_ReceiveAck() != 0)
|
||
{
|
||
I2C_Stop();
|
||
return 1;
|
||
}
|
||
|
||
// 6.发送页写数据与接受应答信号
|
||
for(i = 0; i < DISP_BUFFER_SIZE; i++)
|
||
{
|
||
I2C_SendByte(disp_buffer[i]);
|
||
I2C_ReceiveAck();
|
||
}
|
||
|
||
// 7.发送停止信号
|
||
I2C_Stop();
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 下发显示使能指令
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note NONE
|
||
* @author jarvis
|
||
* @date 2025.11.25
|
||
*/
|
||
static void ht16k33_chip_disp_enable(void)
|
||
{
|
||
|
||
// 发送显示使能命令(不闪烁)
|
||
I2C_Start();
|
||
I2C_SendByte(HT16K33_ADDR);
|
||
if(I2C_ReceiveAck() != 0)
|
||
{
|
||
I2C_Stop();
|
||
}
|
||
I2C_SendByte(HT16K33_CMD_DISPLAY_ON);
|
||
if(I2C_ReceiveAck() != 0)
|
||
{
|
||
I2C_Stop();
|
||
}
|
||
I2C_Stop();
|
||
FL_DelayMs(1);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 初始化芯片
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note NONE
|
||
* @author jarvis
|
||
* @date 2025.11.25
|
||
*/
|
||
void ht16k33_chip_init(void)
|
||
{
|
||
// 释放总线
|
||
SDA_SET();
|
||
SCL_SET();
|
||
FL_DelayMs(1); // 上电后等待复位完成(至少1ms)
|
||
|
||
// 1. 发送系统时钟使能命令
|
||
I2C_Start();
|
||
I2C_SendByte(HT16K33_ADDR); // 从机地址+写操作
|
||
if(I2C_ReceiveAck() != 0)
|
||
{
|
||
I2C_Stop();
|
||
}
|
||
I2C_SendByte(HT16K33_CMD_SYSTEM_ON);
|
||
if(I2C_ReceiveAck() != 0)
|
||
{
|
||
I2C_Stop();
|
||
}
|
||
I2C_Stop();
|
||
FL_DelayMs(1);
|
||
|
||
|
||
|
||
// 3. 发送最大亮度命令
|
||
I2C_Start();
|
||
I2C_SendByte(HT16K33_ADDR);
|
||
if(I2C_ReceiveAck() != 0)
|
||
{
|
||
I2C_Stop();
|
||
}
|
||
I2C_SendByte(HT16K33_CMD_DIMMING_MAX);
|
||
if(I2C_ReceiveAck() != 0)
|
||
{
|
||
I2C_Stop();
|
||
}
|
||
I2C_Stop();
|
||
FL_DelayMs(1);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief 根据UI配置信息刷新HT16K33显存缓冲区
|
||
* @param ui - UIElements类型的UI配置结构体,包含显示模式、数值、指示灯状态等信息
|
||
* @retval uint8_t - 刷新结果:0表示刷新成功
|
||
* @note 1. 支持累时模式(DISPLAY_MODE_TIMER)、氧浓度模式(DISPLAY_MODE_OXYGEN)、错误模式(DISPLAY_MODE_ERROR)三种显示模式
|
||
* 2. 氧浓度值范围限制为0-999(对应显示0.0%-99.9%),累时数值范围限制为0-19999
|
||
* 3. 包含断码表SEG_TAB,支持0-9数字、'-'、空格、'E'、'L'、'P'、'H'字符显示
|
||
* 4. 控制OK灯、报警灯、清洁滤网提示、更换过滤盒提示的显示状态
|
||
* 5. 刷新显存后自动调用ht16k33_send_buffer函数下发数据到屏幕
|
||
* @author jarvis
|
||
* @date 2025.11.25
|
||
*/
|
||
static void ht16k33_refresh_disp(UIElements ui)
|
||
{
|
||
// uint8_t o2_hund, o2_ten, o2_unit; // 百位、十位、个位
|
||
// uint8_t wh_ten_thou, wh_thou, wh_hund, wh_ten, wh_unit; // 万位、千位、百位、十位、个位
|
||
|
||
// 定义断码表(共阴极7段数码管)
|
||
uint8_t SEG_TAB[SEG_TABLE_SIZE] =
|
||
{
|
||
//--0--,--1--,--2--,--3--,--4--,--5--,--6--,--7--,--8--,--9--,
|
||
0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,
|
||
//'-', ' ', 'E', 'L', 'P', 'H', 'C', 'F', 'U', 'A',
|
||
0x40, 0x00, 0x79, 0x38, 0x73, 0x76, 0x39, 0x71, 0x3E, 0x77,
|
||
};
|
||
|
||
// 0.断码表检查并赋值
|
||
ui.disp_info.seg_index.first_8_index = (ui.disp_info.seg_index.first_8_index >= SEG_TABLE_SIZE)?(SEG_TABLE_SIZE-1):ui.disp_info.seg_index.first_8_index;
|
||
ui.disp_info.seg_index.second_8_index = (ui.disp_info.seg_index.second_8_index >= SEG_TABLE_SIZE)?(SEG_TABLE_SIZE-1):ui.disp_info.seg_index.second_8_index;
|
||
ui.disp_info.seg_index.third_8_index = (ui.disp_info.seg_index.third_8_index >= SEG_TABLE_SIZE)?(SEG_TABLE_SIZE-1):ui.disp_info.seg_index.third_8_index;
|
||
ui.disp_info.seg_index.fourth_8_index = (ui.disp_info.seg_index.fourth_8_index >= SEG_TABLE_SIZE)?(SEG_TABLE_SIZE-1):ui.disp_info.seg_index.fourth_8_index;
|
||
|
||
ht16k33_disp_buff[6] = SEG_TAB[ui.disp_info.seg_index.first_8_index];
|
||
ht16k33_disp_buff[4] = SEG_TAB[ui.disp_info.seg_index.second_8_index];
|
||
ht16k33_disp_buff[2] = SEG_TAB[ui.disp_info.seg_index.third_8_index];
|
||
ht16k33_disp_buff[0] = SEG_TAB[ui.disp_info.seg_index.fourth_8_index];
|
||
|
||
|
||
// 1.OK灯显示状态处理
|
||
if(ui.ok_led_show == 1)
|
||
{
|
||
ht16k33_disp_buff[12] |= 0x03;
|
||
}else{
|
||
ht16k33_disp_buff[12] &= ~(0x03);
|
||
}
|
||
|
||
// 2.报警暂停等状态处理
|
||
if(ui.alarm_led_show == 1)
|
||
{
|
||
ht16k33_disp_buff[12] |= 0x0C;
|
||
}else{
|
||
ht16k33_disp_buff[12] &= ~(0x0C);
|
||
}
|
||
|
||
// 3.清洁滤网 100h清洁一次
|
||
if(ui.clean_filter_show == 1)
|
||
{
|
||
ht16k33_disp_buff[6] |= 0x80;
|
||
ht16k33_disp_buff[4] |= 0x80;
|
||
|
||
ht16k33_disp_buff[7] |= 0x07;
|
||
ht16k33_disp_buff[5] |= 0x07;
|
||
}else{
|
||
ht16k33_disp_buff[6] &= ~ 0x80;
|
||
ht16k33_disp_buff[4] &= ~ 0x80;
|
||
|
||
ht16k33_disp_buff[7] &= ~ 0x07;
|
||
ht16k33_disp_buff[5] &= ~0x07;
|
||
}
|
||
|
||
// 4.更换过滤盒 10000h更换过滤盒
|
||
if(ui.replace_box_show == 1)
|
||
{
|
||
ht16k33_disp_buff[2] |= 0x80;
|
||
ht16k33_disp_buff[3] |= 0x07;
|
||
}else{
|
||
ht16k33_disp_buff[2] &= ~ 0x80;
|
||
ht16k33_disp_buff[3] &= ~ 0x07;
|
||
}
|
||
|
||
|
||
// 5.累时中文字符
|
||
if(ui.total_time_chn == 1)
|
||
{
|
||
ht16k33_disp_buff[12] |= 0xF0; // “累时”显示
|
||
ht16k33_disp_buff[13] |= 0x03;
|
||
|
||
ht16k33_disp_buff[1] |= 0x01; // “h”显示
|
||
}else{
|
||
|
||
ht16k33_disp_buff[12] &= ~ 0xF0;// “累时”不显示
|
||
ht16k33_disp_buff[13] &= ~ 0x03;
|
||
|
||
ht16k33_disp_buff[1] &= ~ 0x01; // “h”不显示
|
||
}
|
||
|
||
|
||
// 6.氧浓度中文字符
|
||
if(ui.oxg_concentration_chn == 1)
|
||
{
|
||
|
||
ht16k33_disp_buff[10] |= 0xFF; // “氧浓度”显示
|
||
ht16k33_disp_buff[1] |= 0x06; //“%”显示
|
||
|
||
ht16k33_disp_buff[0] |= 0x80; // “.”显示
|
||
|
||
}else{
|
||
|
||
ht16k33_disp_buff[10] &= ~ 0xFF; // “氧浓度”不显示
|
||
ht16k33_disp_buff[1] &= ~ 0x06; //“%”不显示
|
||
|
||
ht16k33_disp_buff[0] &= ~ 0x80; // “.”不显示
|
||
}
|
||
|
||
// 7.最左侧的数字一是否显示
|
||
if(ui.disp_info.seg_index.num1_is_show == 1)
|
||
{
|
||
|
||
ht16k33_disp_buff[11] |= 0x03;
|
||
}else{
|
||
|
||
ht16k33_disp_buff[11] &=~ 0x03;
|
||
}
|
||
|
||
|
||
ht16k33_send_buffer(ht16k33_disp_buff);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/**
|
||
* @brief HT16K33屏幕初始化与刷新函数
|
||
* @param NONE
|
||
* @retval NONE
|
||
* @note 1. 函数执行流程:释放I2C总线→系统时钟使能→显示使能→设置最大亮度→刷新显示内容
|
||
* 2. 上电后等待1ms确保芯片复位完成,每步I2C操作后有1ms延时保证稳定性
|
||
* 3. 涉及的HT16K33命令宏需提前定义:HT16K33_CMD_SYSTEM_ON(系统使能)、HT16K33_CMD_DISPLAY_ON(显示使能)、HT16K33_CMD_DIMMING_MAX(最大亮度)
|
||
* 4. 内部调用ht16k33_refresh_disp函数刷新显示内容,依赖全局变量ui的配置信息
|
||
* 5. 该函数已弃用,建议使用任务与队列形式进行内容刷新
|
||
* @author jarvis
|
||
* @date 2025.11.25
|
||
*/
|
||
void ht16k33_refresh_screen(void)
|
||
{
|
||
|
||
ht16k33_chip_init(); // 初始化芯片配置最大亮度
|
||
ht16k33_chip_disp_enable();
|
||
|
||
ht16k33_refresh_disp(ui); // 根据ui变量中的值刷新屏幕
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/************************ (C) COPYRIGHT YUWELL *****END OF FILE****/
|