K1Guitar/device/TM1617/Drv_TM1617_RGB.c

299 lines
7.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @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();
}