通过这1小时23分钟的超长视频学习,认识到需要学习的内容太多,需要更多时间的消化,感谢冲哥,大半夜的录视频教学。
主程序代码简洁多了:
#include "config.h" //调用头文件,""本工程文件目录下
#include "task.h"
#include "io.h"
char *USER_DEVICEDESC = NULL;
char *USER_PRODUCTDESC = NULL;
char *USER_STCISPCMD = "@STCISP#";
void main(void)
{
Sys_init();
usb_init(); //USB CDC 接口配置 初始化
IE2 |= 0x80; //使能USB中断
Timer0_Init();//定时器初始化
EA = 1; //开启总中断
while (DeviceState != DEVSTATE_CONFIGURED);//等待USB完成配置
while(1)
{
if (bUsbOutReady)
{
//USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
//printf("P2%d\r\n",num); //%字符的格式含义:%s把后面""内的字符替换,\r\n为输出自动换行
usb_OUT_done();
}
Task_Pro_Handler_Callback(); //执行功能函数
}
}
void Timer0_Isr(void) interrupt 1 //1MS执行一次
{
Task_Marks_Handler_Callback(); //系统计时
}
【重做三个实验之一】AiCube 实验一:直接 printf_usb("Hello World !\r\n")
32位8051单片机入门的第一个完整的C语言程序
今天有最新版的AIapp-ISP-V6.95V 下载,开始AiCube生成完整的C语言程序,真的是太方便啦,是我们初学者的福音。
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2025-06-21) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h" //默认已包含stdio.h、intrins.h、ai_usb.h等头文件
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
//<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
// 在此添加用户主函数初始化代码
//<<AICUBE_USER_MAIN_INITIAL_END>>
SYS_Init();
//<<AICUBE_USER_MAIN_CODE_BEGIN>>
// 在此添加主函数中运行一次的用户代码
//<<AICUBE_USER_MAIN_CODE_END>>
while (1)
{
// USBLIB_OUT_Done(); //查询方式处理USB接收的数据
printf_usb("Hello World!~o~laohu_zhou\r\n");
//<<AICUBE_USER_MAIN_LOOP_BEGIN>>
// 在此添加主函数中用户主循环代码
//<<AICUBE_USER_MAIN_LOOP_END>>
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
P0M0 = 0x00; P0M1 = 0x00; //初始化P0口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //初始化P1口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //初始化P2口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //初始化P3口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //初始化P4口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //初始化P5口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //初始化P6口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //初始化P7口为准双向口模式
CLK_Init(); //时钟模块初始化
USBLIB_Init(); //USB库初始化
//<<AICUBE_USER_INITIAL_CODE_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_INITIAL_CODE_END>>
EnableGlobalInt(); //使能全局中断
}
////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
do
{
NOP(34); //(MAIN_Fosc + 500000) / 1000000 - 6
} while (--us);
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
////////////////////////////////////////
// 时钟初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void CLK_Init(void)
{
CLK_SYSCLK_Divider(10); //切换主时钟前先将系统时钟降频
HIRC_40M(); //选择内部预置的频率
CLK_MCLK_HIRC(); //选择内部高精度HIRC作为主时钟
CLK_MCLK2_BYPASS(); //旁路MCLK2,直接使用MCLK选择
CLK_SYSCLK_Divider(1); //设置系统时钟分频系数
CLK_HSIOCK_MCLK(); //选择MCLK主时钟作为高速外设时钟源
CLK_HSIOCK_Divider(1); //设置高速外设时钟预分频系数
CLK_SPICLK_Divider(1); //设置SPI时钟预分频系数
CLK_I2SCLK_Divider(1); //设置I2S时钟预分频系数
CLK_PWMACLK_Divider(1); //设置PWMA时钟预分频系数
CLK_PWMBCLK_Divider(1); //设置PWMB时钟预分频系数
CLK_TFPUCLK_Divider(1); //设置TFPU时钟预分频系数
//<<AICUBE_USER_CLOCK_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_CLOCK_INITIAL_END>>
}
////////////////////////////////////////
// USB库初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_Init(void)
{
usb_init(); //初始化USB模块
USB_SetIntPriority(0); //设置中断为最低优先级
set_usb_ispcmd("@STCISP#"); //设置USB不停电下载命令
//<<AICUBE_USER_USBLIB_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_USBLIB_INITIAL_END>>
}
////////////////////////////////////////
// 等待USB配置完成函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_WaitConfiged(void)
{
while (DeviceState != DEVSTATE_CONFIGURED) //等待USB完成配置
WDT_Clear(); //清看门狗定时器 (防止硬件自动使能看门狗)
}
////////////////////////////////////////
// USB设备接收数据处理程序
// 入口参数: 无
// 函数返回: 无
// bUsbOutReady:USB设备接收数据标志位
// OutNumber:USB设备接收到的数据长度
// UsbOutBuffer:保存USB设备接收到的数据
////////////////////////////////////////
void USBLIB_OUT_Done(void)
{
if (bUsbOutReady) //查询是否有接收到USB主机发送数据
{
//<<AICUBE_USER_USBLIB_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
USB_SendData(UsbOutBuffer, OutNumber); //原路返回, 用于测试
//在此处添加用户处理接收数据的代码
//<<AICUBE_USER_USBLIB_ISR_CODE1_END>>
usb_OUT_done(); //当前包的数据处理完成,通知USB主机可以发送下一包数据
}
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
【重做三个实验之二】AiCube 实验二:查询方式,查询到电脑命令后,
printf_usb("Hello World !\r\n")
这次的实验与上一个的实验相比,除了查询方式处理命令之外,在AiCube项目创建助手的“新建AiCube项目”的“项目文件类型”勾选了“多代码文件项目”,生成的main.c主程序代码简洁多了
main.c:
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2025-06-21) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h" //默认已包含stdio.h、intrins.h、ai_usb.h等头文件
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
//<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
// 在此添加用户主函数初始化代码
//<<AICUBE_USER_MAIN_INITIAL_END>>
SYS_Init();
//<<AICUBE_USER_MAIN_CODE_BEGIN>>
// 在此添加主函数中运行一次的用户代码
//<<AICUBE_USER_MAIN_CODE_END>>
while (1)
{
USBLIB_OUT_Done(); //查询方式处理USB接收的数据
//<<AICUBE_USER_MAIN_LOOP_BEGIN>>
// 在此添加主函数中用户主循环代码
if (bUsbOutReady)
{
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
if (UsbOutBuffer == 6)
printf_usb("Hello World!~o~laohu_zhou\r\n");//如果接收到6,就打印Hello World!~o~laohu_zhou
else
if (UsbOutBuffer == 7)
printf_usb("China!~o~laohu_zhou\r\n");//如果接收到7,就打印China!~o~laohu_zhou
}
//<<AICUBE_USER_MAIN_LOOP_END>>
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
P0M0 = 0x00; P0M1 = 0x00; //初始化P0口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //初始化P1口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //初始化P2口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //初始化P3口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //初始化P4口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //初始化P5口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //初始化P6口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //初始化P7口为准双向口模式
CLK_Init(); //时钟模块初始化
USBLIB_Init(); //USB库初始化
//<<AICUBE_USER_INITIAL_CODE_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_INITIAL_CODE_END>>
EnableGlobalInt(); //使能全局中断
}
////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
do
{
NOP(34); //(MAIN_Fosc + 500000) / 1000000 - 6
} while (--us);
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
【重做三个实验之三】 中断方式,单片机USB中断接收服务函数收到命令后,
printf_usb("Hello World !\r\n")
AiCube工具真的是太方便了,希望STC能够继续完善,并支持以前生产的单片机。
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: main.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
// 1. (2025-06-22) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>
#include "config.h" //默认已包含stdio.h、intrins.h、ai_usb.h等头文件
//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
//<<AICUBE_USER_INCLUDE_END>>
//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>
////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
//<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
// 在此添加用户主函数初始化代码
//<<AICUBE_USER_MAIN_INITIAL_END>>
SYS_Init();
//<<AICUBE_USER_MAIN_CODE_BEGIN>>
// 在此添加主函数中运行一次的用户代码
//<<AICUBE_USER_MAIN_CODE_END>>
while (1)
{
//<<AICUBE_USER_MAIN_LOOP_BEGIN>>
// 在此添加主函数中用户主循环代码
//<<AICUBE_USER_MAIN_LOOP_END>>
}
}
////////////////////////////////////////
// 系统初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void SYS_Init(void)
{
EnableAccessXFR(); //使能访问扩展XFR
AccessCodeFastest(); //设置最快速度访问程序代码
AccessIXramFastest(); //设置最快速度访问内部XDATA
IAP_SetTimeBase(); //设置IAP等待参数,产生1us时基
P0M0 = 0x00; P0M1 = 0x00; //初始化P0口为准双向口模式
P1M0 = 0x00; P1M1 = 0x00; //初始化P1口为准双向口模式
P2M0 = 0x00; P2M1 = 0x00; //初始化P2口为准双向口模式
P3M0 = 0x00; P3M1 = 0x00; //初始化P3口为准双向口模式
P4M0 = 0x00; P4M1 = 0x00; //初始化P4口为准双向口模式
P5M0 = 0x00; P5M1 = 0x00; //初始化P5口为准双向口模式
P6M0 = 0x00; P6M1 = 0x00; //初始化P6口为准双向口模式
P7M0 = 0x00; P7M1 = 0x00; //初始化P7口为准双向口模式
USBLIB_Init(); //USB库初始化
//<<AICUBE_USER_INITIAL_CODE_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_INITIAL_CODE_END>>
EnableGlobalInt(); //使能全局中断
}
////////////////////////////////////////
// 微秒延时函数
// 入口参数: us (设置延时的微秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_us(uint16_t us)
{
do
{
NOP(34); //(MAIN_Fosc + 500000) / 1000000 - 6
} while (--us);
}
////////////////////////////////////////
// 毫秒延时函数
// 入口参数: ms (设置延时的毫秒值)
// 函数返回: 无
////////////////////////////////////////
void delay_ms(uint16_t ms)
{
uint16_t i;
do
{
i = MAIN_Fosc / 6000;
while (--i);
} while (--ms);
}
////////////////////////////////////////
// USB库初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_Init(void)
{
usb_init(); //初始化USB模块
USB_SetIntPriority(3); //设置中断为最高优先级
set_usb_OUT_callback(USBLIB_OUT_Callback); //设置USB中断回调函数
set_usb_ispcmd("@STCISP#"); //设置USB不停电下载命令
//<<AICUBE_USER_USBLIB_INITIAL_BEGIN>>
// 在此添加用户初始化代码
//<<AICUBE_USER_USBLIB_INITIAL_END>>
}
////////////////////////////////////////
// 等待USB配置完成函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void USBLIB_WaitConfiged(void)
{
while (DeviceState != DEVSTATE_CONFIGURED) //等待USB完成配置
WDT_Clear(); //清看门狗定时器 (防止硬件自动使能看门狗)
}
////////////////////////////////////////
// USB设备接收数据中断回调程序
// 入口参数: 无
// 函数返回: 无
// OutNumber:USB设备接收到的数据长度
// UsbOutBuffer:保存USB设备接收到的数据
////////////////////////////////////////
void USBLIB_OUT_Callback(void)
{
//<<AICUBE_USER_USBLIB_ISR_CODE1_BEGIN>>
// 在此添加中断函数用户代码
USB_SendData(UsbOutBuffer, OutNumber); //原路返回, 用于测试
//在此处添加用户处理接收数据的代码
if (UsbOutBuffer == 6)
printf_usb("Hello World !^o^laohu_zhou\r\n"); //接收到数据6后打印“Hello World !^o^laohu_zhou”
else if (UsbOutBuffer == 7)
printf_usb("China !^o^laohu_zhou\r\n"); //接收到数据7后打印“China !^o^laohu_zhou”
//<<AICUBE_USER_USBLIB_ISR_CODE1_END>>
}
//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>
收到了实验箱,感谢司经理的热心帮助。
实验箱主控芯片AI8051U,做工不错,就是感觉盒子有点厚。
继续打卡学习冲哥的视频实验。
实验箱接上usb电源就是时钟显示,加入两个按键调节,不做实验的时候就下载时钟程序做时钟用,真好。
建议可以做下面这3个最简单的程序
【新提醒】还是从 printf_usb("Hello World !\r\n") 开始,《单片机原理及应用》入门@Ai8051U - 51 发烧友,UAC,极致音频,大国工匠,艺术人生,乐林漫步 国芯技术交流网站 - AI32位8051交流社区
已经做过了{:4_202:} 学习感悟之实战:第九集 数码管
学习了本集,购买配件做了一个时钟,几块钱的成本:一块TM1637显示模块、一块STC8G1K08A核心板、2个按钮开关,在面包板连接测试没问题。
#include <STC8G.H>
#include <intrins.h>
// 定义TM1637引脚
sbit TM1637_CLK = P5^4;
sbit TM1637_DIO = P5^5;
// 定义按键引脚
sbit KEY_UP = P3^2; // 调分钟加
sbit KEY_DOWN = P3^3;// 调小时加
// 数码管显示缓冲区
unsigned char DisplayBuffer = {0, 0, 0, 0};
// 时间变量
unsigned char hour = 12;
unsigned char minute = 0;
unsigned char second = 0;
bit blink_state = 0;
// 数码管编码表 (共阳数码管)
// 位定义: DP-G-F-E-D-C-B-A
const unsigned char SegmentCode[] = {
0x3F, // 0 (00111111)
0x06, // 1 (00000110)
0x5B, // 2 (01011011)
0x4F, // 3 (01001111)
0x66, // 4 (01100110)
0x6D, // 5 (01101101)
0x7D, // 6 (01111101)
0x07, // 7 (00000111)
0x7F, // 8 (01111111)
0x6F// 9 (01101111)
};
// 精确延时函数
void DelayUs(unsigned char t)
{
while(t--);
}
// TM1637起始信号
void TM1637_Start()
{
TM1637_CLK = 1;
TM1637_DIO = 1;
DelayUs(2);
TM1637_DIO = 0;
DelayUs(2);
TM1637_CLK = 0;
DelayUs(2);
}
// TM1637停止信号
void TM1637_Stop()
{
TM1637_CLK = 0;
TM1637_DIO = 0;
DelayUs(2);
TM1637_CLK = 1;
DelayUs(2);
TM1637_DIO = 1;
DelayUs(2);
}
// TM1637写一个字节
bit TM1637_WriteByte(unsigned char data_val)
{
unsigned char i;
bit ack;
for(i = 0; i < 8; i++)
{
TM1637_CLK = 0;
DelayUs(2);
TM1637_DIO = (data_val & 0x01) ? 1 : 0;
data_val >>= 1;
DelayUs(2);
TM1637_CLK = 1;
DelayUs(2);
}
TM1637_CLK = 0;
TM1637_DIO = 1;
DelayUs(2);
TM1637_CLK = 1;
DelayUs(2);
ack = TM1637_DIO;
TM1637_CLK = 0;
DelayUs(2);
return ack;
}
// 设置显示数据
void TM1637_SetDisplay()
{
unsigned char i;
TM1637_Start();
TM1637_WriteByte(0x40);// 数据命令: 固定地址, 普通模式
TM1637_Stop();
TM1637_Start();
TM1637_WriteByte(0xC0);// 地址命令: 从地址0开始
for(i = 0; i < 4; i++)
{
TM1637_WriteByte(DisplayBuffer);
}
TM1637_Stop();
TM1637_Start();
TM1637_WriteByte(0x88);// 显示控制: 开显示, 0x8F亮度最大,0x88最小
TM1637_Stop();
}
// 更新显示缓冲区
void UpdateDisplayBuffer()
{
DisplayBuffer = SegmentCode; // 小时十位
DisplayBuffer = SegmentCode; // 小时个位
DisplayBuffer = SegmentCode; // 分钟十位
DisplayBuffer = SegmentCode; // 分钟个位
// 添加冒号(秒闪烁)
if(blink_state)
{
DisplayBuffer |= 0x80;// 设置小数点(冒号)
}
else
{
DisplayBuffer &= 0x7F;// 清除小数点(冒号)
}
}
// 初始化定时器0
void Timer0_Init()
{
AUXR &= 0x7F;// 定时器时钟12T模式
TMOD &= 0xF0;// 设置定时器模式
TMOD |= 0x01;// 16位定时器模式
TH0 = 0xFC; // 设置定时初值(1ms)
TL0 = 0x66;
TR0 = 1; // 启动定时器0
ET0 = 1; // 允许定时器0中断
EA = 1; // 开总中断
}
//// 延时函数
//void DelayMs(unsigned int ms)
//{
// unsigned int i, j;
// for(i = 0; i < ms; i++)
// for(j = 0; j < 1000; j++);
//}
// 按键扫描函数(改进版)
void KeyScan() {
static unsigned char key_up_cnt = 0;
static unsigned char key_down_cnt = 0;
static unsigned char key_both_cnt = 0;
static bit key_up_pressed = 0;
static bit key_down_pressed = 0;
static bit key_both_pressed = 0;
// 检测同时按下
if(KEY_UP == 0 && KEY_DOWN == 0) {
key_both_cnt++;
if(key_both_cnt > 5 && !key_both_pressed) {
key_both_pressed = 1;
if(++hour >= 24) hour = 0;
UpdateDisplayBuffer();
TM1637_SetDisplay();
}
} else {
key_both_cnt = 0;
key_both_pressed = 0;
}
// 检测单独按下P3.2(分钟增加)
if(KEY_UP == 0 && KEY_DOWN == 1) {
key_up_cnt++;
if(key_up_cnt > 5 && !key_up_pressed) {
key_up_pressed = 1;
if(++minute >= 60) minute = 0;
second = 0; //同时复位秒
UpdateDisplayBuffer();
TM1637_SetDisplay();
}
} else {
key_up_cnt = 0;
key_up_pressed = 0;
}
// 检测单独按下P3.3(分钟减少)
if(KEY_DOWN == 0 && KEY_UP == 1) {
key_down_cnt++;
if(key_down_cnt > 5 && !key_down_pressed) {
key_down_pressed = 1;
if(--minute >= 60) minute = 59;
second = 0; //同时复位秒
UpdateDisplayBuffer();
TM1637_SetDisplay();
}
} else {
key_down_cnt = 0;
key_down_pressed = 0;
}
}
// 主函数
void main()
{
// 初始化IO口
P3M0 &= ~(0x0C);// P3.2和P3.3设置为准双向口
P3M1 &= ~(0x0C);
P5M0 &= ~(0x30);// P5.4和P5.5设置为准双向口
P5M1 &= ~(0x30);
// 启用内部上拉电阻
P3 |= 0x0C;// P3.2和P3.3上拉
// 初始化定时器
Timer0_Init();
// 初始化显示
UpdateDisplayBuffer();
TM1637_SetDisplay();
while(1)
{
KeyScan();
}
}
// 定时器0中断服务函数
void Timer0_ISR() interrupt 1
{
static unsigned int count = 0;
TH0 = 0xFC; // 重新加载初值(1ms)
TL0 = 0x66;
count++;
if(count >= 1004)// 1秒(加或减1会使每天影响86.4秒)
{
count = 0;
second++;
blink_state = ~blink_state;// 闪烁状态切换
if(second >= 60)
{
second = 0;
minute++;
if(minute >= 60)
{
minute = 0;
hour++;
if(hour >= 24)
{
hour = 0;
}
}
}
// 更新显示
UpdateDisplayBuffer();
TM1637_SetDisplay();
}
}
页:
1
[2]