299 lines
7.6 KiB
C
299 lines
7.6 KiB
C
/*
|
||
* @Author: CTW
|
||
* @Date: 2025-11-07 14:37:55
|
||
* @FilePath: \PhoenixSMGT_Testproject\Drivers\TM1617\Drv_TM1617_RGB.c
|
||
* @note: 从 STM32 HAL 库移植到 AT32F403A,软件模拟时序(GPIO 位翻转)
|
||
* - HAL_GPIO_WritePin/ReadPin/Init -> at32f403a_407 库 GPIO 函数
|
||
* - Delay_us / Delay_ms / HAL_Delay -> 内置忙等延时
|
||
*/
|
||
#include "Drv_TM1617_RGB.h"
|
||
|
||
uint8_t rgb_color_seq[] = {COLOR_R, COLOR_G, COLOR_B, COLOR_YEL, COLOR_CYA, COLOR_PUR, COLOR_WHT}; // 颜色流转序列
|
||
uint8_t color_idx = 0; // 颜色索引
|
||
|
||
/* ================= 底层原语(AT32 GPIO) ================= */
|
||
|
||
#define TM1617_DIO_H() gpio_bits_set(DIO_PORT, DIO_PIN)
|
||
#define TM1617_DIO_L() gpio_bits_reset(DIO_PORT, DIO_PIN)
|
||
#define TM1617_CLK_H() gpio_bits_set(CLK_PORT, CLK_PIN)
|
||
#define TM1617_CLK_L() gpio_bits_reset(CLK_PORT, CLK_PIN)
|
||
#define TM1617_STB_H() gpio_bits_set(STB_PORT, STB_PIN)
|
||
#define TM1617_STB_L() gpio_bits_reset(STB_PORT, STB_PIN)
|
||
|
||
/* 忙等延时:约 1us(NOP 循环,不依赖 SysTick/RTOS) */
|
||
static void TM1617_Delay1us(void)
|
||
{
|
||
volatile uint32_t i = 24; /* 240MHz 下约 1us,可实测微调 */
|
||
while (i--) __NOP();
|
||
}
|
||
|
||
/* 忙等延时:约 1ms(NOP 循环) */
|
||
static void TM1617_Delay1ms(void)
|
||
{
|
||
volatile uint32_t i = 24000; /* 240MHz 下约 1ms */
|
||
while (i--) __NOP();
|
||
}
|
||
|
||
/* DIO 引脚切换为输出模式(推挽) */
|
||
static void TM1617_DIO_Output(void)
|
||
{
|
||
gpio_init_type g;
|
||
gpio_default_para_init(&g);
|
||
g.gpio_mode = GPIO_MODE_OUTPUT;
|
||
g.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
|
||
g.gpio_pull = GPIO_PULL_NONE;
|
||
g.gpio_pins = DIO_PIN;
|
||
gpio_init(DIO_PORT, &g);
|
||
}
|
||
|
||
/* DIO 引脚切换为输入模式(读按键) */
|
||
static void TM1617_DIO_Input(void)
|
||
{
|
||
gpio_init_type g;
|
||
gpio_default_para_init(&g);
|
||
g.gpio_mode = GPIO_MODE_INPUT;
|
||
g.gpio_pull = GPIO_PULL_NONE;
|
||
g.gpio_pins = DIO_PIN;
|
||
gpio_init(DIO_PORT, &g);
|
||
}
|
||
|
||
/* GPIO初始化 */
|
||
void TM1617_GPIO_Init(void)
|
||
{
|
||
gpio_init_type g;
|
||
|
||
/* 使能 GPIOB / GPIOC 时钟 */
|
||
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
|
||
crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
|
||
|
||
/* CLK(PB0)、STB(PC15)、DIO(PC4):推挽输出,初始拉高 */
|
||
gpio_default_para_init(&g);
|
||
g.gpio_mode = GPIO_MODE_OUTPUT;
|
||
g.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
|
||
g.gpio_pull = GPIO_PULL_NONE;
|
||
g.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
|
||
|
||
g.gpio_pins = CLK_PIN;
|
||
gpio_init(CLK_PORT, &g);
|
||
g.gpio_pins = STB_PIN;
|
||
gpio_init(STB_PORT, &g);
|
||
g.gpio_pins = DIO_PIN;
|
||
gpio_init(DIO_PORT, &g);
|
||
|
||
TM1617_CLK_H();
|
||
TM1617_STB_H();
|
||
TM1617_DIO_H();
|
||
}
|
||
|
||
/* 读取1字节数据(STB已拉低,CLK上升沿读) */
|
||
uint8_t TM1617_ReadByte(void)
|
||
{
|
||
uint8_t i, data = 0;
|
||
|
||
TM1617_DIO_Input();
|
||
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
data >>= 1; // 低位先收,右移占位
|
||
TM1617_CLK_L();
|
||
TM1617_Delay1us();
|
||
|
||
// 时钟上升沿读数据
|
||
TM1617_CLK_H();
|
||
if (gpio_input_data_bit_read(DIO_PORT, DIO_PIN) == SET)
|
||
{
|
||
data |= 0x80; // 最高位置1
|
||
}
|
||
TM1617_Delay1us();
|
||
}
|
||
|
||
TM1617_DIO_Output();
|
||
|
||
return data;
|
||
}
|
||
|
||
/* TM1617写1字节数据(低位先行,CLK上升沿锁存) */
|
||
void TM1617_WriteByte(uint8_t data)
|
||
{
|
||
uint8_t i;
|
||
for (i = 0; i < 8; i++)
|
||
{
|
||
TM1617_CLK_L();
|
||
TM1617_Delay1us();
|
||
|
||
// DIO写当前bit(低位先行)
|
||
if (data & 0x01) TM1617_DIO_H();
|
||
else TM1617_DIO_L();
|
||
TM1617_Delay1us();
|
||
|
||
// CLK拉高,锁存数据
|
||
TM1617_CLK_H();
|
||
TM1617_Delay1us();
|
||
|
||
data >>= 1;
|
||
}
|
||
}
|
||
|
||
/* TM1617上电清零(避免显示乱码,必须执行) */
|
||
void TM1617_Clear(void)
|
||
{
|
||
TM1617_STB_L();
|
||
TM1617_Delay1us();
|
||
|
||
TM1617_WriteByte(0x40); // 写数据+地址自动增加
|
||
TM1617_WriteByte(0xC0); // 起始地址 C0H
|
||
for (uint8_t i = 0; i < 6; i++)
|
||
{
|
||
TM1617_WriteByte(0x00); // 6个显存地址清零
|
||
}
|
||
|
||
TM1617_STB_H();
|
||
TM1617_Delay1us();
|
||
}
|
||
|
||
/* TM1617初始化(设置显示模式+初始辉度) */
|
||
void TM1617_Init(void)
|
||
{
|
||
TM1617_GPIO_Init(); /* 必须先配引脚/时钟,否则 CLK/STB/DIO 浮空,灯不亮 */
|
||
TM1617_Clear();
|
||
TM1617_Delay1ms();
|
||
|
||
// 配置显示模式:3位7段(指令0x03)
|
||
TM1617_STB_L();
|
||
TM1617_Delay1us();
|
||
TM1617_WriteByte(0x03);
|
||
TM1617_STB_H();
|
||
TM1617_Delay1us();
|
||
|
||
// 配置初始辉度:最高(0x8F)
|
||
TM1617_STB_L();
|
||
TM1617_Delay1us();
|
||
TM1617_WriteByte(0x8F);
|
||
TM1617_STB_H();
|
||
TM1617_Delay1us();
|
||
}
|
||
|
||
/* 设置RGB颜色+辉度(brightness:0~7,对应8级PWM) */
|
||
void TM1617_SetRGB(uint8_t color, uint8_t brightness)
|
||
{
|
||
if (brightness > 7) brightness = 7;
|
||
|
||
// 写颜色数据(地址自动增加模式)
|
||
TM1617_STB_L();
|
||
TM1617_Delay1us();
|
||
TM1617_WriteByte(0x40); // 数据命令:写数据+地址自增
|
||
TM1617_WriteByte(0xC0); // 起始地址 C0H
|
||
TM1617_WriteByte(color); // RGB颜色数据
|
||
TM1617_STB_H();
|
||
TM1617_Delay1us();
|
||
|
||
// 写辉度命令
|
||
TM1617_STB_L();
|
||
TM1617_Delay1us();
|
||
TM1617_WriteByte(0x88 + brightness); // 辉度指令 0x88~0x8F
|
||
TM1617_STB_H();
|
||
TM1617_Delay1us();
|
||
}
|
||
|
||
/* 按键扫描函数:返回SEG5~SEG8对应按键状态 */
|
||
KeyStatusTypeDef TM1617_ScanFkey(void)
|
||
{
|
||
uint8_t keyData[5] = {0};
|
||
KeyStatusTypeDef keyState = KEY_NULL;
|
||
|
||
TM1617_STB_L();
|
||
TM1617_Delay1us();
|
||
|
||
TM1617_WriteByte(0x42); // 读键数据命令
|
||
TM1617_Delay1us();
|
||
|
||
// 按顺序读取5字节数据
|
||
keyData[0] = TM1617_ReadByte(); // BYTE1
|
||
keyData[1] = TM1617_ReadByte(); // BYTE2
|
||
keyData[2] = TM1617_ReadByte(); // BYTE3(SEG5、SEG6)
|
||
keyData[3] = TM1617_ReadByte(); // BYTE4(SEG7、SEG8)
|
||
keyData[4] = TM1617_ReadByte(); // BYTE5
|
||
|
||
TM1617_STB_H();
|
||
TM1617_Delay1us();
|
||
|
||
// 解析SEG5~SEG8对应按键(按下为1)
|
||
if (keyData[2] & 0x01)
|
||
{
|
||
keyState = KEY_MAIN_A;
|
||
}
|
||
else if (keyData[2] & 0x08)
|
||
{
|
||
keyState = KEY_MAIN_B;
|
||
}
|
||
else if (keyData[3] & 0x01)
|
||
{
|
||
keyState = KEY_MAIN_C;
|
||
}
|
||
else if (keyData[3] & 0x08)
|
||
{
|
||
keyState = KEY_MAIN_D;
|
||
}
|
||
|
||
return keyState;
|
||
}
|
||
|
||
/* RGB呼吸流转 */
|
||
void RGB_Breath_Flow(void)
|
||
{
|
||
static uint8_t brightness;
|
||
|
||
// 吸气:暗→亮
|
||
for (brightness = 0; brightness < 8; brightness++)
|
||
{
|
||
TM1617_SetRGB(rgb_color_seq[color_idx], brightness);
|
||
TM1617_Delay1ms();
|
||
// 近似 100ms
|
||
for (volatile uint32_t k = 0; k < 100; k++) TM1617_Delay1ms();
|
||
}
|
||
|
||
// 呼气:亮→暗
|
||
for (brightness = 7; brightness > 0; brightness--)
|
||
{
|
||
TM1617_SetRGB(rgb_color_seq[color_idx], brightness);
|
||
TM1617_Delay1ms();
|
||
for (volatile uint32_t k = 0; k < 100; k++) TM1617_Delay1ms();
|
||
}
|
||
|
||
// 切换下一种颜色
|
||
color_idx = (color_idx + 1) % 7;
|
||
}
|
||
|
||
/* 最小化测试:让RGB灯常亮(白色,最高辉度) */
|
||
void RGB_Test_On(uint8_t u8Color)
|
||
{
|
||
TM1617_Clear();
|
||
TM1617_Delay1ms();
|
||
|
||
// 配置显示模式
|
||
TM1617_STB_L();
|
||
TM1617_Delay1us();
|
||
TM1617_WriteByte(0x03);
|
||
TM1617_STB_H();
|
||
TM1617_Delay1us();
|
||
|
||
// 写颜色数据到 C0H
|
||
TM1617_STB_L();
|
||
TM1617_Delay1us();
|
||
TM1617_WriteByte(0x40);
|
||
TM1617_WriteByte(0xC0);
|
||
TM1617_WriteByte(u8Color);
|
||
TM1617_STB_H();
|
||
TM1617_Delay1us();
|
||
|
||
// 配置最高辉度
|
||
TM1617_STB_L();
|
||
TM1617_Delay1us();
|
||
TM1617_WriteByte(0x8F);
|
||
TM1617_STB_H();
|
||
TM1617_Delay1us();
|
||
|
||
// 保持
|
||
for (volatile uint32_t k = 0; k < 500; k++) TM1617_Delay1ms();
|
||
}
|