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)
/* 忙等延时:约 1usNOP 循环,不依赖 SysTick/RTOS */
static void TM1617_Delay1us(void)
{
volatile uint32_t i = 24; /* 240MHz 下约 1us可实测微调 */
while (i--) __NOP();
}
/* 忙等延时:约 1msNOP 循环) */
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颜色+辉度brightness0~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(); // BYTE3SEG5、SEG6
keyData[3] = TM1617_ReadByte(); // BYTE4SEG7、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();
}