本帖最后由 芯圣电子官方QQ 于 2023-7-20 10:47 编辑
HC89F0541_TimeAdjustLight说明:
*重要备注: v1.1版测试 输出控制 工作为高电平
* 版本: V1.1
* 日期: 2020.09.28
* 测试: 按键控制 定时器调光灯 (6档亮度,逐渐或直接 变化 )
* 基本功能:
1-. 上电指示灯 LED1~4 灭, OUTLED5 OUTLED6 OUTLED7 灯关闭,
2-. KEY1按键长按与 短按功能(短按灯亮度加 长按 开关机).
3-. KEY2按键长按与 短按功能(短按灯亮度减 长按 灯亮度调整 逐渐或直接 变化).
* 硬件相关:
2个按键口 P05(KEY1) P06(KEY2)
4个指示灯 LED1~4 (P10 P11短按) (P12 P13长按) 指示
3个灯控制 OUTLED5 OUTLED6 OUTLED7 (P15 P16 P17)
* 相关说明:
1. 使用定时器1 产生100khz(10us)定时器
2. 100hz(10ms)(LED状态刷新)
3. 0~1000 占空比调整
*重要备注: v1.1版测试 输出控制 工作为高电平
原理图 与 代码 见附件
HC89F0541_TimeAdjustLight_SCH_20201029_V1.pdf
HC89F0541_TimeAdjustLight_OL_Project.zip
代码如下:
main_OL.c
//--头文件-----
#define ALLOCATE_EXTERN
#include "HC89F0541.h"
//--宏定义--
#define CPU_RUN_CLK 16000000L //16Mhz
#define LED1 P1_0 // 硬件LED io口
#define LED2 P1_1 // 硬件LED io口
#define LED3 P1_2 // 硬件LED io口
#define LED4 P1_3 // 硬件LED io口
//--按键宏定义--
#define KEYINPUT1 P0_5 //硬件set键 io口
#define KEYINPUT2 P0_6 //硬件add键 io口
#define KEY_INTERVAL_TIME_XD 20 //按键间隔时间 消抖
#define OUTLED1 P1_5 // LED灯 驱动1
#define OUTLED2 P1_6 // LED灯 驱动2
#define OUTLED3 P1_7 // LED灯 驱动3
// //-V1.0- 低工作-高关闭
//#define OUT_CONTROL_ON 0 //输出控制 开 0
//#define OUT_CONTROL_OFF 1 //输出控制 关 1
//-V1.1- 高工作-低关闭
#define OUT_CONTROL_ON 1 //输出控制 开 1
#define OUT_CONTROL_OFF 0 //输出控制 关 0
//-占空比的百分比数据表- 根据实际需求情况修改 1~999之间-
//-说明:占空比调整值 范围热大 单色与三色 调整效果更好-
unsigned int code DutyDataTable1[6]={3,12,48,140,250,999}; //
unsigned int code DutyDataTable2[6]={3,12,48,140,250,999}; //
unsigned int code DutyDataTable3[6]={3,12,48,140,250,999}; //
//--占空比的百分比数据表- 测试修改1-
//unsigned int code DutyDataTable1[6]={3,12,48,140,250,999}; //
//unsigned int code DutyDataTable2[6]={12,48,140,250,999,3}; //
//unsigned int code DutyDataTable3[6]={48,140,250,999,3,12}; //
volatile unsigned char vGu8DutyIndex = 0; //占空比索引 DutyDataTable1~3[1]
volatile unsigned char vGu8WorkFlag = 0; //工作状态标志 变量
volatile unsigned int vGu16CycleCnt = 0; //周期计数变量
volatile unsigned int vGu16DutyCnt = 0; //占空比计数变量
//--占空比 比较值 与 调整值 3组LED值
//-可以修改 占空比的百分比数据表 --
volatile unsigned int vGu16DutyCompare1 = 0; //占空比 比较值
volatile unsigned int vGu16DutyUpdata1 = 0; //占空比 调整值
volatile unsigned int vGu16DutyCompare2 = 0; //占空比 比较值
volatile unsigned int vGu16DutyUpdata2 = 0; //占空比 调整值
volatile unsigned int vGu16DutyCompare3 = 0; //占空比 比较值
volatile unsigned int vGu16DutyUpdata3 = 0; //占空比 调整值
//---按键LED 指示灯用---
volatile unsigned int vGu16KeyLedCnt = 0; // 按键操作LED计数
volatile unsigned char vGu8KeyLedEn = 0; // 按键操作LED指示控制
//-LED亮度逐渐变化 标志位-gradually--
volatile unsigned char vGu8LEDGraduallyFlag = 1; // LED灯亮度逐渐变化 标志位 1使能 0除能
volatile unsigned char vGu8T0RH; //
volatile unsigned char vGu8T0RL; //
//-按键相关变量-
volatile unsigned char vGu8SingleKeySec = 0; //扫描按键的 独立按键值
//--变量区--
//--函数区--
void DelayMs(unsigned int ms); //ms延时函数
void ConfigTimer0(unsigned int ms); //定时器0配置
void ConfigTimer1(unsigned int us); //定时器1配置
void KeyScan(void); //按键的扫描
void KeyLedDelay(void); //按键LED延时函数
void SingleKeyTask(void); //独立按键任务
void LedDutyWorkEn(unsigned char En); //LED占空比工作控制函数
void main()
{
/************************************系统初始化****************************************/
CLKSWR = 0x51; //选择内部高频RC为系统时钟,内部高频RC 2分频,Fosc=16MHz
CLKDIV = 0x01; //Fosc 1分频得到Fcpu,Fcpu=16MHz
/**********************************端口消抖初始化**************************************/
// P0M0 = 0x00; //P00设置为模拟输入
// P0M1 = 0x60; //P01设置为非施密特数字带上拉输入
// P2M1 = 0x50; //P21设置为非施密特数字带下拉输入
// P2M3 = 0x68; //P23设置为施密特数字带上拉输入
// P3M4 = 0x58; //P34设置为施密特数字带下拉输入
// P3M5 = 0x70; //P35设置为非施密特数字带上下拉输入
// P2M5 = 0x78; //P25设置为施密特数字带上下拉输入
// P2M6 = 0xC0; //P26设置为推挽输出
// P2M7 = 0xC4; //P27设置为开漏输出
// P1M7 = 0xE4; //P17设置为开漏带上拉输出
P1M0 = 0xC2; //P10设置为推挽输出
P1M1 = 0xC2; //P11设置为推挽输出
P1M2 = 0xC2; //P12设置为推挽输出
P1M3 = 0xC2; //P13设置为推挽输出
P1M5 = 0xC2; //P16设置为推挽输出
P1M6 = 0xC2; //P16设置为推挽输出
P1M7 = 0xC2; //P17设置为推挽输出
P0M5 = 0x60; //P05设置为非施密特数字带上拉输入
P0M6 = 0x60; //P06设置为非施密特数字带上拉输入
vGu16DutyCompare1 = DutyDataTable1[vGu8DutyIndex]; //占空比 比较值 1组
vGu16DutyCompare2 = DutyDataTable2[vGu8DutyIndex]; //占空比 比较值 2组
vGu16DutyCompare3 = DutyDataTable3[vGu8DutyIndex]; //占空比 比较值 3组
DelayMs(10); //ms延时函数
ConfigTimer0(1); //定时器0配置
ConfigTimer1(10); //定时器1配置 10US
LedDutyWorkEn(0); //LED占空比工作控制函数
while(1)
{
//---测试用--
// LED1 = ~LED1; //
// DelayMs(500); //ms延时函数
SingleKeyTask(); //独立按键任务
}
}
/***********************************
函数名称:DelayMs(unsigned int ms)
输入参数1:ms 延时整数
输入参数2:
输出: 无
功能说明:ms延时函数。阻塞型延时
函数放入的位置:
CPU_RUN_CLK/1000)/10; 自适应延时
***********************************/
void DelayMs(unsigned int ms) //ms延时函数
{
unsigned int i; //
for(;ms>0;ms--)
{
for(i=(CPU_RUN_CLK/1000)/10;i>0;i--);
}
}
/* ***************************************
函数名称: ConfigTimer0
输入参数1: ms 配置定时器 的 毫秒数
输入参数2: 无
输出参数: 无
功能说明: 定时器0配置
函数一般放在位置: 一般主函数初始化
//-备注 n个ms(毫秒)时钟小于65536
//-当前16MHZ 12分频 ms在1~49
//-当前16MHZ 1分频 ms在1~4
****************************************** */
void ConfigTimer0(unsigned int ms) //定时器0配置
{
unsigned long tmp; //
//--定时器0 12分频 或 1分频
//-备注 n个ms(毫秒)时钟小于65536
//-当前16MHZ 12分频 ms在1~49
//-当前16MHZ 1分频 ms在1~4
//TCON1 &= 0xFE; //定时器0 12分频 默认
tmp = CPU_RUN_CLK / 12 /1000 ; //1毫秒需要的时钟
//TCON1 |= 0x01; //定时器0 1分频
//tmp = CPU_RUN_CLK /1000 ; //1毫秒需要的时钟
tmp = tmp * ms; // ms个毫秒时钟
//tmp = tmp + 10; // 定时快了 微调加
//tmp = tmp - 10; // 定时慢了 微调减
tmp = 65536 - tmp; //得到填入的 定时器装载值
TMOD &= 0xF0; //清定时器0模式设置
TMOD |= 0x01; //清定时器0模式设置
vGu8T0RH = (unsigned char)(tmp >> 8); //保存装载值的高8位 变量
vGu8T0RL = (unsigned char)tmp; //保存装载值的低8位 变量
TH0 = vGu8T0RH; //装载值的高8位
TL0 = vGu8T0RL; // 装载值的低8位
IP0 &= 0xF3; //bit3~2 定时器0的 优先级0(最低) 默认
//IP0 |= 0x04; //bit3~2 定时器0的 优先级1
//IP0 |= 0x08; //bit3~2 定时器0的 优先级2
//IP0 |= 0x0C; //bit3~2 定时器0的 优先级3
ET0 = 1; //定时器0 中断 使能
EA = 1; //总中断 使能
TR0 = 1; //定时器 0 运行
}
/* **************************************
函数名称: InterruptTimer0()
输入参数: 无
输出参数: 无
功能说明: 定时器0 中断函数 中断号 1
备注说明:
***************************************** */
void InterruptTimer0() interrupt 1
{
// static unsigned int i = 0; //测试用
TH0 = vGu8T0RH; //装载值的高8位
TL0 = vGu8T0RL; // 装载值的低8位
// if(++i >= 500) //测试用
// {
// i=0; //
// LED1 = ~LED1;
// }
KeyScan(); //按键的扫描
//按键LED指示灯 亮延时
if(vGu8KeyLedEn == 1) //按键LED指示灯 亮延时
{
vGu16KeyLedCnt--; //
if(0 == vGu16KeyLedCnt)
{
vGu8KeyLedEn = 0; //按键LED指示灯控制关闭
LED1 = 1; // 关闭指示灯 LED1
LED2 = 1; // 关闭指示灯 LED2
LED3 = 1; // 关闭指示灯 LED3
}
}
//- *备注按键调整占空比值后,直接调整亮度
// *可以删除下面 或 vGu16DutyCompare 与 vGu16DutyUpdata 赋值一样
//-按键调整占空比值 用定时方式 亮度逐渐变化调整
if(vGu16DutyCompare1 != vGu16DutyUpdata1) //1组
{
if(vGu16DutyCompare1 > vGu16DutyUpdata1)
{
vGu16DutyCompare1--; //
}
else
{
vGu16DutyCompare1++; //
}
}
if(vGu16DutyCompare2 != vGu16DutyUpdata2) //2组
{
if(vGu16DutyCompare2 > vGu16DutyUpdata2)
{
vGu16DutyCompare2--; //
}
else
{
vGu16DutyCompare2++; //
}
}
if(vGu16DutyCompare3 != vGu16DutyUpdata3) //3组
{
if(vGu16DutyCompare3 > vGu16DutyUpdata3)
{
vGu16DutyCompare3--; //
}
else
{
vGu16DutyCompare3++; //
}
}
//--------------------
}
/* ***************************************
函数名称: ConfigTimer1
输入参数1: us 配置定时器 的 微秒数
输入参数2: 无
输出参数: 无
功能说明: 定时器1配置
函数一般放在位置: 一般主函数初始化
//-当前16MHZ 1分频 1us在16时钟
//- 65536 / 16 = 4096us
此处设置100khz(10us)
****************************************** */
void ConfigTimer1(unsigned int us) //定时器1配置
{
unsigned long tmp; //
//--定时器1 1分频
TCON1 |= 0x10; //定时器0 1分频
tmp = CPU_RUN_CLK /1000000 ; //1微秒需要的时钟
tmp = tmp * us; // ms个毫秒时钟
//tmp = tmp + 10; // 定时快了 微调加
//tmp = tmp - 10; // 定时慢了 微调减
tmp = 65536 - tmp; //得到填入的 定时器装载值
TMOD &= 0x0F; //清定时器1模式设置 模式为0 默认
//TMOD |= 0x10; //清定时器1模式为1
TH1 = (unsigned char)(tmp >> 8); //装载值的高8位
TL1 = (unsigned char)tmp; //装载值的低8位
IP0 &= 0x3F; //bit7~6 定时器1的 优先级0(最低) 默认
//IP0 |= 0x40; //bit7~6 定时器1的 优先级1
//IP0 |= 0x80; //bit7~6 定时器1的 优先级2
//IP0 |= 0xC0; //bit7~6 定时器1的 优先级3
ET1 = 1; //定时器1 中断 使能
EA = 1; //总中断 使能
//TR1 = 1; //定时器 1 运行
}
/* **************************************
函数名称: InterruptTimer1()
输入参数: 无
输出参数: 无
功能说明: 定时器0 中断函数 中断号 3
备注说明:
***************************************** */
void InterruptTimer1() interrupt 3
{
// //--定时器1测试
// static unsigned int i = 0; //
// if(++i >= 50000)
// {
// i=0; //
// LED1 = ~LED1;
// }
if(1 == vGu8WorkFlag)
{
vGu16CycleCnt++; //
vGu16DutyCnt++; //
if(vGu16CycleCnt >= 1000)
{
vGu16CycleCnt = 0; //周期计数变量
vGu16DutyCnt = 0; //占空比计数变量
//--打开--
OUTLED1 = OUT_CONTROL_ON; // 输出控制 开启 OUTLED1
OUTLED2 = OUT_CONTROL_ON; // 输出控制 开启 OUTLED2
OUTLED3 = OUT_CONTROL_ON; // 输出控制 开启 OUTLED3
}
if(vGu16DutyCnt >= vGu16DutyCompare1) //-1组
{
OUTLED1 = OUT_CONTROL_OFF; // 输出控制 关闭
}
if(vGu16DutyCnt >= vGu16DutyCompare2) //-2组
{
OUTLED2 = OUT_CONTROL_OFF; // 输出控制 关闭
}
if(vGu16DutyCnt >= vGu16DutyCompare3) //-3组
{
OUTLED3 = OUT_CONTROL_OFF; // 输出控制 关闭
}
}
}
/* ************************************************
函数名称: KeyScan(void)
功能说明: 按键的扫描
输入参数:
输出参数:
日期与备注: 202010
函数放在 定时 中断函数里
功能描述:短按-长按(1秒)
************************************************ */
void KeyScan(void) //按键扫描短按-长按(1秒)
{
static unsigned int Su16KeyCnt[2] = {0,0}; //按键计数 变量
static unsigned char Su8KeyLock[2] = {0,0}; //按键状态锁 变量
static unsigned char Su8ShortKeyFlag[2] = {0,0}; //按键短按标志位 变量
//-按键1处理
if(0 != KEYINPUT1) //
{
Su16KeyCnt[0] = 0; //按键计数清零
Su8KeyLock[0] = 0; //按键状态锁 使能
if(1 == Su8ShortKeyFlag[0])
{
Su8ShortKeyFlag[0] = 0; //短按标志位 清零
vGu8SingleKeySec = 1; // 短按 键码值
}
}
else if(0 == Su8KeyLock[0]) //
{
Su16KeyCnt[0]++; // 按键按下计数
//--消抖后 短按值--
if(Su16KeyCnt[0] == KEY_INTERVAL_TIME_XD) //消抖后 短按
{
Su8ShortKeyFlag[0] = 1; //短按标志位 使能
}
if(Su16KeyCnt[0] >= 1000) //按键间隔时间 长按
{
Su8KeyLock[0] = 1; //按键状态锁 使能
Su8ShortKeyFlag[0] = 0; //短按标志位 清零
vGu8SingleKeySec = 11; // 长按 键码值
}
}
//-按键2处理
if(0 != KEYINPUT2) //
{
Su16KeyCnt[1] = 0; //按键计数清零
Su8KeyLock[1] = 0; //按键状态锁 使能
if(1 == Su8ShortKeyFlag[1])
{
Su8ShortKeyFlag[1] = 0; //短按标志位 清零
vGu8SingleKeySec = 2; //短按 键码值
}
}
else if(0 == Su8KeyLock[1]) //
{
Su16KeyCnt[1]++; //按键按下计数
//--消抖后 短按值--
if(Su16KeyCnt[1] == KEY_INTERVAL_TIME_XD) //消抖后 短按
{
Su8ShortKeyFlag[1] = 1; //短按标志位 使能
}
if(Su16KeyCnt[1] >= 1000) //按键间隔时间 长按
{
Su8KeyLock[1] = 1; //按键状态锁 使能
Su8ShortKeyFlag[1] = 0; //短按标志位 清零
vGu8SingleKeySec = 12; //长按 键码值
}
}
}
/* ***********************************************
函数名称: KeyLedDelay
功能说明: 按键LED延时函数
输入参数: 无
输出参数: 无
日期与备注: 202010
************************************************* */
void KeyLedDelay(void) //按键LED延时函数
{
vGu16KeyLedCnt = 100; //按键LED指示灯 赋延时值
vGu8KeyLedEn = 1; //按键LED指示灯 控制 开
}
/* ***********************************************
函数名称: SingleKeyTask
功能说明: 独立按键任务函数
输入参数: 无
输出参数: 无
日期与备注: 202010
************************************************* */
void SingleKeyTask(void) //独立按键任务
{
if(0 == vGu8SingleKeySec)
{
return;
}
switch(vGu8SingleKeySec)
{
case 1:
if(1 == vGu8WorkFlag)
{
LED1 = 0; //
KeyLedDelay(); //按键LED延时函数
}
if(vGu8DutyIndex < 5 && 1 == vGu8WorkFlag)
{
vGu8DutyIndex++;
//-按键调整占空比值后,直接调整亮度
//vGu16DutyCompare1 = DutyDataTable1[vGu8DutyIndex]; //-按键调整占空比值后,直接调整亮度
//-按键调整占空比值后 增加一个变量 用定时方式 亮度逐渐变化调整
vGu16DutyUpdata1 = DutyDataTable1[vGu8DutyIndex]; //-按键调整占空比值 1组
vGu16DutyUpdata2 = DutyDataTable2[vGu8DutyIndex]; //-按键调整占空比值 2组
vGu16DutyUpdata3 = DutyDataTable3[vGu8DutyIndex]; //-按键调整占空比值 3组
}
if(0 == vGu8LEDGraduallyFlag) //逐渐标志为0 则 将<比较值>同时更新,与<更新值>一样.
{
vGu16DutyCompare1 = vGu16DutyUpdata1; //1组
vGu16DutyCompare2 = vGu16DutyUpdata2; //2组
vGu16DutyCompare3 = vGu16DutyUpdata3; //3组
}
vGu8SingleKeySec = 0; //
break;
case 2:
if(1 == vGu8WorkFlag)
{
LED2 = 0; //
KeyLedDelay(); //按键LED延时函数
}
if(vGu8DutyIndex > 0 && 1 == vGu8WorkFlag)
{
vGu8DutyIndex--;
//-按键调整占空比值后,直接调整亮度
//vGu16DutyCompare1 = DutyDataTable1[vGu8DutyIndex]; //-按键调整占空比值后,直接调整亮度
//-按键调整占空比值后 增加一个变量 用定时方式 亮度逐渐变化调整
vGu16DutyUpdata1 = DutyDataTable1[vGu8DutyIndex]; //-按键调整占空比值 1组
vGu16DutyUpdata2 = DutyDataTable2[vGu8DutyIndex]; //-按键调整占空比值 2组
vGu16DutyUpdata3 = DutyDataTable3[vGu8DutyIndex]; //-按键调整占空比值 3组
if(0 == vGu8LEDGraduallyFlag) //逐渐标志为0 则 将<比较值>同时更新,与<更新值>一样.
{
vGu16DutyCompare1 = vGu16DutyUpdata1; //1组
vGu16DutyCompare2 = vGu16DutyUpdata2; //2组
vGu16DutyCompare3 = vGu16DutyUpdata3; //3组
}
}
vGu8SingleKeySec = 0; //
break;
case 11:
//LED4 = ~LED4; //
if(0 == vGu8WorkFlag)
{
vGu8WorkFlag = 1; //
}
else
{
vGu8WorkFlag = 0; //
}
LedDutyWorkEn(vGu8WorkFlag); //LED占空比工作控制函数
vGu8SingleKeySec = 0; //
break;
case 12:
//LED3 = ~LED3; //
if(1 == vGu8WorkFlag)
{
LED3 = 0; //
KeyLedDelay(); //按键LED延时函数
}
if(1 == vGu8LEDGraduallyFlag)
{
vGu8LEDGraduallyFlag = 0; // LED灯亮度逐渐变化 标志位 1使能 0除能
}
else
{
vGu8LEDGraduallyFlag = 1; // LED灯亮度逐渐变化 标志位 1使能 0除能
}
vGu8SingleKeySec = 0; //
break;
default: break;
}
}
/* ***********************************************
函数名称: LedDutyWorkEn
功能说明: LED占空比工作控制函数
输入参数: 无
输出参数: 无
日期与备注: 202010
************************************************* */
void LedDutyWorkEn(unsigned char En) //LED占空比工作控制函数
{
if(0 == En)
{
LED1 = 1; // 关闭指示灯 LED1
LED2 = 1; // 关闭指示灯 LED2
LED3 = 1; // 关闭指示灯 LED3
LED4 = 1; // 关闭指示灯 LED4
TR1 = 0; // 定时器1 关闭
OUTLED1 = OUT_CONTROL_OFF; // 输出控制 关闭
OUTLED2 = OUT_CONTROL_OFF; // 输出控制 关闭
OUTLED3 = OUT_CONTROL_OFF; // 输出控制 关闭
}
else
{
vGu16CycleCnt = 0; //周期计数变量 清零
vGu16DutyCnt = 0; //占空比计数变量 清零
TR1 = 1; // 定时器1 运行
LED4 = 0; // 开启指示灯 LED4
}
}
|
共2人点赞
|