- 积分
- 1491
- 在线时间
- 2013 小时
- 最后登录
- 2024-4-28
- 阅读权限
- 70
- 精华
- 0
- UID
- 897598
- 帖子
- 1384
- 精华
- 0
- 经验
- 1491 点
- 金钱
- 1290 ¥
- 注册时间
- 2021-2-4
|
本帖最后由 mchoi518 于 2024-2-25 10:25 编辑
去年年底开始学习软控,先是做了一个简单的STM8S103主控,只能出声的ES9038Q2M解码,新手入门可以参考下面帖子,有软控开发基础知识。
http://bbs.hifidiy.net/forum.php ... &tid=1501716&extra=
为了更上一步,为自己制定了如下目标,并制作了一个配套的解码+耳放 “学习机”。
1) 解码芯片软控(软件I2C):单声道输出设置、SPDIF输入设置(CSR8675蓝牙模块是SPDIF输出)、音量控制
2) 输入和输出选择:输入USB/BT选择,输出PHONE/RCA选择
3) 继电器音调 or DAC内置音量选择
4) 音量调节和静音:音量可以通过继电器音调,也可以通过DAC音量寄存器。静音状态下调整音量和音量控制方式时可以回复音量
5) EC11编码器功能:旋转调音量,短按输入选择,长按(1秒以上)输出选择
6) OLED屏显(软件SPI):开机画面显示,正常播放画面显示。显示输入、输出、音量控制、音量及单位、PCMDSD、采样率显示。电路原因位深没能读取。
7) 红外遥控:以上2345所有功能,外加通过重新执行main函数得到软重启效果 (本解码耳放电路没有设计遥控开关,只有背面电源开关)
8) 通过STM8S芯片内置EEPROM保存所有状态,开机载入关机前状态。
软件部分特别感谢”丰年好大雪”大师,从他那里学到很多~
1. 学习机硬件部分
先上硬件系统整体示意图
全部是手里闲置原件做的,除了机壳和PCB新购~
▶主电源板子没有原理图,用sprint layout画的,简单的整流稳压电路。 输出1个12v,2个5v,一组+-15v。
▶解码耳放板子原理图、PCB、实物图
为什么可以叫耳放,因为IV LPF电路增益大概4~5倍,可以输出8~10VRMS,输出缓冲运放使用SS2590,静态电流30ma~
主控芯片用了STM8S105,有32K闪存,字体库够用
*电路原理图已修改,与下面代码一致
继电器音量用了7个继电器,0~127DB,1DB步进。可以去下面链接计算阻值
https://www.vaneijndhoven.net/jo ... lculator/index.html
继电器音量电路:用PD0~PD6的7个脚控制,用ULN2003电流放大非门芯片,
可以把音量VOLUME值的2位码直接输出,用一个GPIO_Write(GPIOD, VOLUME);语句搞定。
通过ULN2003得到反码,7个继电器的另一头是12v,低电平吸合~
开始把红外画到PF端口,但PF没有中断,只能飞线改成PE端口
I2C改SPI,在芯片上加了3根线。I2C容易花屏,SPI好多了
*电路原理图已修改,与下面代码一致
▶制作,这个壳子商家面板开孔费太贵,买了个电磨机自己开的孔,电磨机比解码器还贵~
▶整机效果,屏幕效果
贴片焊的比较整齐吧,哈哈~
虽然只是学习机,不能做的太寒酸,否则没有学习热情~哈哈
2. 软件部分
下面代码也是STM8S标准库写的。
如果新手,开发环境搭建、基本的调试等等,可以去之前的帖子学习: http://bbs.hifidiy.net/forum.php ... &tid=1501716&extra=
▶主程序main.c
所有行都加了备注,尽量模块化,重复和无用代码删除,变量等代码可读性都较好。
而且经过了一周的反复调试,自认为没有大的BUG了。
适合新手学习用~哈哈
代码功能的理解,仔细看下面代码注释就可以了~ 可以直接复制了使用。
/*******************************************************************************
代码仅供学习使用,不允许商业用途
STM8S标准库使用:
1) stm8s_clk 时钟
2) stm8s_exti 外部中断,用于编码器和红外遥控
3) stm8s_flash EEPROM存储,用于存储输入/输出/音量/音控方式
4) stm8s_gpio GPIO控制
5) stm8s_tim1 计时器1,用于定时读取解码芯片状态
6) stm8s_tim2 计时器2,用于红外遥控
7) stm8s_tim3 计时器3,用于EC11长按
扩展库使用:
1) i2c.c 软件i2c库文件
2) oled.c 1.3寸12864 OLED购买商家那里得到的
3) remote.c 红外遥控库文件
development by mchoi 20240221
*******************************************************************************/
/**********库文件引用**********/
#include "stm8s.h" // 里面STM8S105定义要打开
#include "oled.h" // OLED附带的SPI程序头文件
#include "bmp.h" // OLED附带的图片程序头文件
#include "i2c.h" // 软件I2C程序头文件
#include "remote.h" // 红外遥控程序头文件
/**********定义固定值**********/
#define EC11_A_PIN GPIO_PIN_5 // 定义EC11编码器引脚A
#define EC11_B_PIN GPIO_PIN_6 // 定义EC11编码器引脚B
#define EC11_E_PIN GPIO_PIN_7 // 定义EC11编码器引脚E
#define DAC_ADDR_L 0x90 // 左声道ES9038Q2M I2C地址,ADDR引脚接地
#define DAC_ADDR_R 0x92 // 右声道ES9038Q2M I2C地址,ADDR引脚拉高
/**********定义全局变量**********/
u8 INPUT; // 输入选择值: 0 USB;1 BT
u8 INPUT_OLD; // 输入选择过去值
u8 OUTPUT; // 输出选择值: 0 PHONE;1 RCA
u8 OUTPUT_OLD; // 输出选择过去值
u8 VOLUME; // 音量: 0~127
u8 VOLUME_OLD; // 音量过去值
u8 VOL255; // DAC寄存器音量格式:0~255
u8 VOLCTRL; // 音量控制方式: 0 继电器音调;1 DAC内置音调
u8 VOLCTRL_OLD; // 音量控制方式过去值
u8 MUTE = 0; // 静音状态值: 0 非静音;1 静音
u8 MUTE_OLD = 0; // 静音状态过去值
u8 RESTART = 0; // main重新执行: 0 非重启;1 重启
u8 IR_DATA[4]; // 数组,遥控器地址码、地址反码、键值码、键值反码
/**********解码器初始化函数**********/
void DAC_Init(void)
{
GPIO_Init(GPIOA, (GPIO_Pin_TypeDef)(GPIO_PIN_1 | GPIO_PIN_2), GPIO_MODE_OUT_PP_HIGH_FAST); // GPIOA初始化,PD1和PD2脚
GPIO_Init(GPIOD, (GPIO_Pin_TypeDef)(GPIO_PIN_ALL), GPIO_MODE_OUT_PP_LOW_FAST); // GPIOD所有引脚初始化低电平,开机静音
GPIO_WriteLow(GPIOA, (GPIO_Pin_TypeDef)GPIO_PIN_1); // 连接两个DAC芯片RESETB脚的PA1输出低电平
delay_ms(2); // 延迟2ms
GPIO_WriteHigh(GPIOA, (GPIO_Pin_TypeDef)GPIO_PIN_1); // 连接两个DAC芯片RESETB脚的PA1输出高电平
delay_ms(2); // 延迟2ms
}
/**********编码器初始化函数**********/
void EC11_Init(void)
{
GPIO_DeInit(GPIOC);
GPIO_Init(GPIOC, (GPIO_Pin_TypeDef)(EC11_A_PIN | EC11_E_PIN), GPIO_MODE_IN_FL_IT); // 配置EC11_A和E引脚为输入,有中断
GPIO_Init(GPIOC, (GPIO_Pin_TypeDef)EC11_B_PIN, GPIO_MODE_IN_PU_NO_IT); // 配置EC11_B引脚为输入,无中断
TIM3_DeInit(); // TIM3初始化,用于编码器按键时间计时
TIM3_TimeBaseInit(TIM3_PRESCALER_16384, 65535); // 16M分频后大概1ms一次计数,65535计数最大值也是溢出值
TIM3_ARRPreloadConfig(ENABLE); // 直到更新事件后,ARR预装载寄存器的值才传给影子寄存器
EXTI_DeInit(); // 外部中断初始化
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOC, EXTI_SENSITIVITY_FALL_ONLY); // 配置外部中断,下降沿触发
rim(); // 开启全局中断
}
/**********TIM1定时器初始化函数**********/
void TIM1_Init(void)
{
TIM1_DeInit(); // TIM1定时器初始化
TIM1_TimeBaseInit(16000,TIM1_COUNTERMODE_UP,1000,3); // 分频16000,上升延计数,计数1000次,3次就是3秒
TIM1_ARRPreloadConfig(ENABLE); // 使能自动重装
TIM1_ITConfig(TIM1_IT_UPDATE,ENABLE); // TIM1中断使能
TIM1_Cmd(ENABLE); // TIM1命令使能
rim(); // 开启全局中断
}
/**********内部EEPROM写函数**********/
void EEPROM_WriteByte(uint16_t address, uint8_t data)
{
FLASH_Unlock(FLASH_MEMTYPE_DATA); // 解锁
FLASH_EraseByte(address); // 擦除
FLASH_ProgramByte(address, data); // 写入数据
FLASH_Lock(FLASH_MEMTYPE_DATA); // 锁定
}
/**********编码器按键时间计时函数**********/
u16 EC11_Time(void)
{
u16 y; // 定义一个临时变量
TIM3_SetCounter(0); // 清空定时器的值
TIM3_Cmd(ENABLE); // 开启定时器
while(!GPIO_ReadInputPin(GPIOC, EC11_E_PIN)){} // 等待低电平结束
y=TIM3_GetCounter(); // 计数结果传给y
TIM3_Cmd(DISABLE); // 关闭定时器
return y; // 返回y值
}
/**********INPUT处理函数**********/
void INPUT_OP(void)
{
if (INPUT == 0)
{
IIC_Write(DAC_ADDR_L,1,0xC4); // 1号寄存器INPUT SELECT : DSD or SERIAL
IIC_Write(DAC_ADDR_R,1,0xC4); // 1号寄存器INPUT SELECT : DSD or SERIAL
OLED_ShowString(0,0,"USB",16); // 显示输入状态
}
else
{
IIC_Write(DAC_ADDR_L,1,0xC1); // 1号寄存器INPUT SELECT : SPDIF
IIC_Write(DAC_ADDR_R,1,0xC1); // 1号寄存器INPUT SELECT : SPDIF
OLED_ShowString(0,0,"BT ",16); // 显示输入状态
}
}
/**********OUTPUT处理函数**********/
void OUTPUT_OP(void)
{
if (OUTPUT == 0)
{
GPIO_WriteLow(GPIOA, (GPIO_Pin_TypeDef)GPIO_PIN_2); // 控制输出继电器
OLED_ShowString(0,3,"PHONE",16); // 显示输出状态
}
else
{
GPIO_WriteHigh(GPIOA, (GPIO_Pin_TypeDef)GPIO_PIN_2); // 控制输出继电器
OLED_ShowString(0,3,"RCA ",16); // 显示输出状态
}
}
/**********VOLUME处理函数**********/
void VOLUME_OP(void)
{
if (VOLCTRL == 0)
GPIO_Write(GPIOD, VOLUME); // 继电器音量更新
else
{
if(VOLUME == 0) VOL255 = 255; // 将显示音量0~127换算成0~255
else VOL255 = 254 - VOLUME * 2;
IIC_Write(DAC_ADDR_L,15,VOL255); // 15号音量寄存器更新
IIC_Write(DAC_ADDR_L,16,VOL255); // 16号音量寄存器更新
IIC_Write(DAC_ADDR_R,15,VOL255); // 15号音量寄存器更新
IIC_Write(DAC_ADDR_R,16,VOL255); // 16号音量寄存器更新
}
OLED_ShowString(110,6,"dB",16); // 显示音量单位
OLED_ShowNum(62,4,VOLUME,3,32); // 显示音量
}
/**********VOLCTRL处理函数**********/
void VOLCTRL_OP(void)
{
if (VOLCTRL == 0)
{
IIC_Write(DAC_ADDR_L,15,0); // 音量寄存器设0最大音量
IIC_Write(DAC_ADDR_L,16,0); // 音量寄存器设0最大音量
IIC_Write(DAC_ADDR_R,15,0); // 音量寄存器设0最大音量
IIC_Write(DAC_ADDR_R,16,0); // 音量寄存器设0最大音量
OLED_ShowString(0,6,"RVOL",16); // 显示音量控制方式-继电器音调
}
else
{
GPIO_Write(GPIOD, 0xFF); // 继电器音量设置最大音量
OLED_ShowString(0,6,"DVOL",16); // 显示音量控制方式-DAC内置音调
}
}
/**********TIM1定时中断处理入口**********/
INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11)
{
sim(); // 停止全局中断
u8 PCMDSD; // 定义一个临时变量保存I2C读取结果
u8 DPLL; // 存储DAC的66~68号寄存器的值
u16 SR=0; // 保存采样率值
/**********读取DAC状态**********/
PCMDSD = IIC_Read(DAC_ADDR_L,96); // I2C读取一个DAC的96号寄存器:DSD 1/49,PCM 2,SPDIF 4/52
DPLL = IIC_Read(DAC_ADDR_L,66); // 读取66~69号寄存器DPLL值
DPLL = IIC_Read(DAC_ADDR_L,67);
DPLL = IIC_Read(DAC_ADDR_L,69);
DPLL = IIC_Read(DAC_ADDR_L,68); // 只判断68号寄存器
if(DPLL == 0) // 如果DPLL位0,无信号
{
OLED_ShowString(48,0," ",16); // PCMDSD显示位置擦除
OLED_ShowString(76,0," ",16); // 采样率数值位置擦除
OLED_ShowString(104,0," ",16); // 采样率单位擦除
}
/**********显示DAC状态**********/
else
{
if(PCMDSD == 1) // 如果值是1,DSD
{
if(DPLL == 57) SR = 64; // 100Mhz时钟,68号寄存器数值对应的DSD格式
if(DPLL == 115) SR = 128;
if(DPLL == 230) SR = 256;
if(DPLL == 205) SR = 512;
OLED_ShowString(48,0,"DSD",16); // 显示DSD
OLED_ShowNum(76,0,SR,3,16); // 屏幕显示DSD格式值
OLED_ShowString(104,0," ",16); // 采样率单位擦除
}
else if(PCMDSD == 2) // 如果值是2,PCM
{
if(DPLL == 28) SR = 44; // 100Mhz时钟,68号寄存器数值对应的采样率
if(DPLL == 31) SR = 48;
if(DPLL == 57) SR = 88;
if(DPLL == 62) SR = 96;
if(DPLL == 115) SR = 176;
if(DPLL == 125) SR = 192;
if(DPLL == 231) SR = 352;
if(DPLL == 251) SR = 384;
OLED_ShowString(48,0,"PCM",16); // 否则显示PCM
OLED_ShowNum(76,0,SR,3,16); // 屏幕显示采样率值
OLED_ShowString(104,0,"Khz",16); // 屏幕显示采样率单位
}
}
TIM1_ClearITPendingBit(TIM1_IT_UPDATE); // TIM1的标志位清零
rim(); // 开启全局中断
}
/**********编码器中断处理入口**********/
INTERRUPT_HANDLER(EXTI_PORTC_IRQHandler, 5)
{
sim(); // 停止全局中断
delay_ms(1); // 基本的去抖动延时
u16 time; // 定义一个临时变量保存编码器按键时间
/**********编码器按键处理**********/
if (GPIO_ReadInputPin(GPIOC, EC11_E_PIN) == 0) // 判断是否E脚触发中断
{
time = EC11_Time(); // 读取按键时间
if(time<1000) // 判断按键时间是否小于1秒
{
if (INPUT==0) INPUT=1; // 更换输入状态,0是USB,1是蓝牙
else INPUT=0;
}
else // 1秒以上视为长按
{
if (OUTPUT==0) OUTPUT=1; // 更换输出状态,0是PHONE,1是RCA
else OUTPUT=0;
}
}
/**********编码器旋转处理**********/
else
{
if (GPIO_ReadInputPin(GPIOC, EC11_B_PIN) == 0) // 判断是否B脚触发中断:B脚低电平顺时针,否则逆时针
{
if (VOLUME<127) VOLUME++; // 音量加,最高127
else VOLUME=127;
}
else // 音量减,最低0
{
if (VOLUME>0) VOLUME--;
else VOLUME=0;
}
}
rim(); // 开启全局中断
}
/**********红外遥控中断处理入口**********/
INTERRUPT_HANDLER(EXTI_PORTE_IRQHandler, 7)
{
u16 time; // 定义临时变量保存高、低电平维持时间
u8 i,j,data=0; // 定义临时变量,用于循环解码
/**********引导码处理**********/
time=IR_GetTime_L(); // 得到低电平时间,函数定义在remote.c
if(time<5500||time>10000)return; // 标准时间: 9000us,否则退出中断服务
time=IR_GetTime_H(); // 得到高电平时间,函数定义在remote.c
if(time<1300||time>5500)return; // 标准时间4500us,否则退出中断服务
/**********重复码处理**********/
if(time>1300&&time<3000) // 先处理重复码,重复码标准时间 2250us
{
if(IR_DATA[2]==128 || IR_DATA[2]==193) // 遥控器上→按键或音量+按键,长按产生重复码
{
if (VOLUME<127) VOLUME++;
else VOLUME=127;
}
if(IR_DATA[2]==129 || IR_DATA[2]==153) // 遥控器上←按键或音量-按键,长按产生重复码
{
if (VOLUME>0) VOLUME--;
else VOLUME=0;
}
delay_ms(1); // 延迟1ms跳过560us信号,长按时下个重复码再次促发中断
return;
}
/**********正常码解码**********/
for(i=0;i<4;i++) // 4组按顺序是:遥控器地址码、地址反码、键值码、键值反码
{
for(j=0;j<8;j++) // 8位数字循环读取
{
time=IR_GetTime_L(); // 得到低电平时间
if(time<400||time>700)return; // 标准时间: 560us,否则退出中断服务
time=IR_GetTime_H(); // 得到高电平时间
if(time>1400&&time<1800) // 数据"1" 1680us
{
data>>=1; // 右移一位
data|=0x80; // 位或10000000
}
else if(time>400&&time<700) // 数据"0" 560us
{
data>>=1; // 右移一位
}
else return; // 否则退出中断服务
}
IR_DATA=data; // 存放解码成功的值
}
/**********键值处理**********/ // 只判断数组第3组8位键值,地址码和反码校验省略
if(IR_DATA[2]==128 || IR_DATA[2]==193) // 音量加
{
if (VOLUME<127) VOLUME++;
else VOLUME=127;
}
if(IR_DATA[2]==129 || IR_DATA[2]==153) // 音量减
{
if (VOLUME>0) VOLUME--;
else VOLUME=0;
}
if(IR_DATA[2]==197) // 输入选择
{
if (INPUT==0) INPUT=1;
else INPUT=0;
}
if(IR_DATA[2]==136) // 输出选择
{
if(OUTPUT==0) OUTPUT=1;
else OUTPUT=0;
}
if(IR_DATA[2]==206) // 音量控制方式选择
{
if(VOLCTRL==0) VOLCTRL=1;
else VOLCTRL=0;
}
if(IR_DATA[2]==130) // 静音
{
if(MUTE==0) MUTE=1;
else MUTE=0;
}
if(IR_DATA[2]==220) // 复位重启
RESTART = 1;
delay_ms(100); // 延迟100ms,跳过一个周期108ms后退出中断服务
return;
}
/**********主程序**********/
void main(void)
{
START:
/**********各种初始化**********/
Clk_Init(); // 时钟初始化,定义在remote.c
IIC_Init(); // I2C初始化,定义在i2c.c
DAC_Init(); // 解码器初始化
EC11_Init(); // 编码器初始化
Remote_Init(); // 遥控初始化,定义在remote.c
OLED_Init(); // OLED初始化,定义在oled.c
/**********开机画面**********/
OLED_ShowString(6,3,"Design",16); // 开机画面,显示本人签名
OLED_ShowString(62,3,"by",16);
OLED_ShowString(86,3,"Mchoi",16);
/**********读取关机前状态**********/
INPUT = FLASH_ReadByte(0x4000); // 读取EEPROM上次保存的输入选择状态
OUTPUT = FLASH_ReadByte(0x4001); // 读取EEPROM上次保存的输出选择状态
VOLUME = FLASH_ReadByte(0x4002); // 读取EEPROM上次保存的音量值
VOLCTRL = FLASH_ReadByte(0x4003); // 读取EEPROM上次保存的音量控制方式
/**********DAC寄存器设置**********/
IIC_Write(DAC_ADDR_L,2,0x30); // MAPPING CH1,将CH1和CH2都设置为CH1
IIC_Write(DAC_ADDR_L,8,0x99); // GPIO CONFIG : INPUT SELECT
IIC_Write(DAC_ADDR_L,11,0x30); // SPDIF SELECT : GPIO1
IIC_Write(DAC_ADDR_L,14,0x42); // SOFT START
IIC_Write(DAC_ADDR_L,21,0x50); // GPIO INPUT SELECT : SPDIF
IIC_Write(DAC_ADDR_R,2,0x35); // MAPPING CH2,将CH1和CH2都设置为CH2
IIC_Write(DAC_ADDR_R,8,0x99); // GPIO CONFIG : INPUT SELECT
IIC_Write(DAC_ADDR_R,11,0x30); // SPDIF SELECT : GPIO1
IIC_Write(DAC_ADDR_R,14,0x42); // SOFT START
IIC_Write(DAC_ADDR_R,21,0x50); // GPIO INPUT SELECT : SPDIF
/**********开机状态处理**********/
delay_ms(3000); // 延迟3秒,开机画面维持3秒
OLED_Clear(); // OLED清屏
INPUT_OP(); // 运行输入处理函数
OUTPUT_OP(); // 运行输出处理函数
VOLUME_OP(); // 运行音量处理函数
VOLCTRL_OP(); // 运行音量控制方式处理函数
TIM1_Init(); // TIM1定时器初始化
/**********主循环**********/ // 通过主循环,各值变化时运行相应操作
while (1)
{
/**********INPUT变化时执行**********/
if (INPUT != INPUT_OLD) // 判断INPUT是否变化
{
INPUT_OLD = INPUT; // 先更新INPUT_OLD
EEPROM_WriteByte(0x4000, INPUT); // 记录新的值到EEPROM
INPUT_OP(); // 运行处理函数
}
/**********OUTPUT变化时执行**********/
if (OUTPUT != OUTPUT_OLD) // 判断OUTPUT是否有变化
{
OUTPUT_OLD = OUTPUT; // 先更新OUTPUT_OLD
EEPROM_WriteByte(0x4001, OUTPUT); // 记录新的值到EEPROM
OUTPUT_OP(); // 运行处理函数
}
/**********VOLUME变化时执行**********/
if (VOLUME != VOLUME_OLD) // 判断VOLUME是否有变化
{
VOLUME_OLD = VOLUME; // 先更新VOLUME_OLD
EEPROM_WriteByte(0x4002, VOLUME); // 记录新的值到EEPROM
if (MUTE==1) MUTE=0; // 如果静音状态,改变MUTE以执行下面MUTE部分
else VOLUME_OP(); // 否则运行处理函数
}
/**********VOLCTRL变化时执行**********/
if (VOLCTRL != VOLCTRL_OLD) // 判断VOLCTRL是否有变化
{
VOLCTRL_OLD = VOLCTRL; // 先更新VOLCTRL_OLD
EEPROM_WriteByte(0x4003, VOLCTRL); // 记录新的值到EEPROM
if (MUTE==1) MUTE=0; // 如果静音状态,改变MUTE以执行下面MUTE部分
else // 否则运行处理函数
{
VOLUME_OP();
VOLCTRL_OP();
}
}
/**********MUTE变化时执行**********/
if (MUTE != MUTE_OLD) // 判断MUTE是否有变化
{
MUTE_OLD = MUTE; // 先更新MUTE_OLD
if (MUTE == 0) // 如果非静音
{
OLED_ShowString(62,4," ",32); // 擦除"MUTE"
VOLUME_OP(); // 恢复音量
VOLCTRL_OP(); // 恢复音量控制方式
}
else // 如果静音
{
GPIO_Write(GPIOD, 0); // 继电器音量设置最小
IIC_Write(DAC_ADDR_L,15,255); // 音量寄存器设置最小
IIC_Write(DAC_ADDR_L,16,255); // 音量寄存器设置最小
IIC_Write(DAC_ADDR_R,15,255); // 音量寄存器设置最小
IIC_Write(DAC_ADDR_R,16,255); // 音量寄存器设置最小
OLED_ShowString(62,4,"MUTE",32); // 显示"MUTE"
}
}
/**********RESTART变化时执行**********/ // 重新执行main函数达到软件重置效果
if (RESTART == 1) // 如果RESTART变为1
{
RESTART = 0; // 先更新RESTART值
TIM1_Init(); // 因TIM1在开机3秒后才初始化,所以这里先处理
goto START; // 回到main函数START位置,重新执行main
}
delay_ms(1); // 延迟1ms循环
}
}
#ifdef USE_FULL_ASSERT // 调试用,使能断言
void assert_failed(u8* file, u32 line)
{
while (1)
{
}
}
#endif
**上面代码整体概括说明:
先定义必要的库函数,针脚,全局变量等;
再定义函数,各种初始化,各种操作可以模块化的;
写中断入口函数,包括定时中断、编码器中断、红外遥控中断;
主程序里面先执行开机各种初始化和屏幕显示、寄存器读取和写入,然后主循环读取各种值的变化。
** 自己的红外遥控器的键值如何知晓?可以先写好代码,在线调试时,读取IR_DATA[2]数值,然后写到程序里
▶main.c和配套的库文件下载
上面代码main.c文件
main.zip
(5.84 KB, 下载次数: 78)
|
评分
-
查看全部评分
|