wuzhengmin 发表于 2026-3-4 20:19:02

接着看exti.c:
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: exti.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
//   1. (2026-03-04) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>


#include "config.h"


//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含
#include "key.h"
#include "led.h"
//<<AICUBE_USER_INCLUDE_END>>


//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>



////////////////////////////////////////
// 外部中断INT0初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI0_Init(void)
{
    INT0_FallingRisingInt();            //设置外部中断为边沿中断 (上升沿+下降沿)
    INT0_SetIntPriority(0);             //设置中断为最低优先级
    INT0_EnableInt();                   //使能外部中断

    //<<AICUBE_USER_EXTI0_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_EXTI0_INITIAL_END>>
}

////////////////////////////////////////
// 外部中断INT1初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI1_Init(void)
{
    INT1_FallingRisingInt();            //设置外部中断为边沿中断 (上升沿+下降沿)
    INT1_SetIntPriority(0);             //设置中断为最低优先级
    INT1_EnableInt();                   //使能外部中断

    //<<AICUBE_USER_EXTI1_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_EXTI1_INITIAL_END>>
}


////////////////////////////////////////
// 外部中断INT0中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI0_ISR(void) interrupt INT0_VECTOR
{
    //<<AICUBE_USER_EXTI0_ISR_CODE1_BEGIN>>
    // 在此添加中断函数用户代码
        //对应P32---K3
        if(KEY3==0)
        {
                delay_ms(10);
                if(KEY3==0)
                {
                        LED3=!LED3;
                        printf_usb("K3(P32)按下!\r\n");                // 发送字符串“K3(P32)按下!”
                }
                       
        }
    //<<AICUBE_USER_EXTI0_ISR_CODE1_END>>
}

////////////////////////////////////////
// 外部中断INT1中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void EXTI1_ISR(void) interrupt INT1_VECTOR
{
    //<<AICUBE_USER_EXTI1_ISR_CODE1_BEGIN>>
    // 在此添加中断函数用户代码
        //对应P33---K4
        if(KEY4==0)
        {
                delay_ms(10);
                if(KEY4==0)
                {
                        LED4=!LED4;
                        printf_usb("K4(P33)按下!\r\n");                // 发送字符串“K4(P33)按下!”
                }
                       
        }
    //<<AICUBE_USER_EXTI1_ISR_CODE1_END>>
}


//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>

wuzhengmin 发表于 2026-3-4 20:21:35

实验现象也和我们预期的一样:

顺利结束本实验

wuzhengmin 发表于 2026-3-5 09:04:53

上面这个外部中断和普通IO口中断,我的旧试验箱有个现象:

按1下开关,有时候会表现为按了2次,我把消抖时间延长到40毫秒

也没有什么改善,这个现象在STC的Ai8051U试验箱和STC的32G12K128试验箱上都没有出现过

可能开关的种类也有影响,如果是实用项目,就一定要解决才行生产.........暂且搁置

今天我们继续学习15.1-定时器中断实验-简介

本讲主要内容
1.实验介绍
2.硬件设计
3.软件设计
4.实验现象

wuzhengmin 发表于 2026-3-5 10:29:09

Ai8051U系列单片机内部设置了6个24位定时器/计数器(8位预分频+16位计)

数)。6个16位定时器TO、T1、T2、T3、T4和T11都具有计数方式和定时方式两种工作方式。

1.2 实验目的
通过定时器TO、T1、T2、T3让D1指示灯间隔100ms闪烁,D2间隔200ms闪烁,D3间隔300ms闪烁,D4间隔400ms闪烁。

本实验使用到硬件资源如下:
(1)定时器
(2)GPIO
(3)LED模块
重点看AiCube配置:

wuzhengmin 发表于 2026-3-5 10:45:06

定时器设置:

wuzhengmin 发表于 2026-3-5 11:31:41

最重要的是timer.c函数:

//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
////////////////////////////////////////
// 在此添加用户文件头说明信息
// 文件名称: timer.c
// 文件描述:
// 文件版本: V1.0
// 修改记录:
//   1. (2026-03-05) 创建文件
////////////////////////////////////////
//<<AICUBE_USER_HEADER_REMARK_END>>


#include "config.h"


//<<AICUBE_USER_INCLUDE_BEGIN>>
// 在此添加用户头文件包含

#include "led.h"
//<<AICUBE_USER_INCLUDE_END>>


//<<AICUBE_USER_GLOBAL_DEFINE_BEGIN>>
// 在此添加用户全局变量定义、用户宏定义以及函数声明
//<<AICUBE_USER_GLOBAL_DEFINE_END>>



////////////////////////////////////////
// 定时器0初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER0_Init(void)
{
#define T0_PSCR               (1)
#define T0_RELOAD               (65536 - (float)SYSCLK / 12 / (T0_PSCR + 1) * 10 / 1000) //定时周期10毫秒

    TIMER0_TimerMode();               //设置定时器0为定时模式
    TIMER0_12TMode();                   //设置定时器0为12T模式
    TIMER0_Mode0();                     //设置定时器0为模式0 (16位自动重载模式)
    TIMER0_DisableGateINT0();         //禁止定时器0门控
    TIMER0_SetIntPriority(0);         //设置中断为最低优先级
    TIMER0_EnableInt();               //使能定时器0中断
    TIMER0_SetPrescale(T0_PSCR);      //设置定时器0的8位预分频
    TIMER0_SetReload16(T0_RELOAD);      //设置定时器0的16位重载值
    TIMER0_Run();                     //定时器0开始运行

    //<<AICUBE_USER_TIMER0_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_TIMER0_INITIAL_END>>
}

////////////////////////////////////////
// 定时器1初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER1_Init(void)
{
#define T1_PSCR               (1)
#define T1_RELOAD               (65536 - (float)SYSCLK / 12 / (T1_PSCR + 1) * 20 / 1000) //定时周期20毫秒

    TIMER1_TimerMode();               //设置定时器1为定时模式
    TIMER1_12TMode();                   //设置定时器1为12T模式
    TIMER1_Mode0();                     //设置定时器1为模式0 (16位自动重载模式)
    TIMER1_DisableGateINT1();         //禁止定时器1门控
    TIMER1_SetIntPriority(0);         //设置中断为最低优先级
    TIMER1_EnableInt();               //使能定时器1中断
    TIMER1_SetPrescale(T1_PSCR);      //设置定时器1的8位预分频
    TIMER1_SetReload16(T1_RELOAD);      //设置定时器1的16位重载值
    TIMER1_Run();                     //定时器1开始运行

    //<<AICUBE_USER_TIMER1_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_TIMER1_INITIAL_END>>
}

////////////////////////////////////////
// 定时器2初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER2_Init(void)
{
#define T2_PSCR               (2)
#define T2_RELOAD               (65536 - (float)SYSCLK / 12 / (T2_PSCR + 1) * 30 / 1000) //定时周期30毫秒

    TIMER2_TimerMode();               //设置定时器2为定时模式
    TIMER2_12TMode();                   //设置定时器2为12T模式
    TIMER2_EnableInt();               //使能定时器2中断
    TIMER2_SetPrescale(T2_PSCR);      //设置定时器2的8位预分频
    TIMER2_SetReload16(T2_RELOAD);      //设置定时器2的16位重载值
    TIMER2_Run();                     //定时器2开始运行

    //<<AICUBE_USER_TIMER2_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_TIMER2_INITIAL_END>>
}

////////////////////////////////////////
// 定时器3初始化函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER3_Init(void)
{
#define T3_PSCR               (20)
#define T3_RELOAD               (65536 - (float)SYSCLK / 12 / (T3_PSCR + 1) * 400 / 1000) //定时周期400毫秒

    TIMER3_TimerMode();               //设置定时器3为定时模式
    TIMER3_12TMode();                   //设置定时器3为12T模式
    TIMER3_EnableInt();               //使能定时器3中断
    TIMER3_SetPrescale(T3_PSCR);      //设置定时器3的8位预分频
    TIMER3_SetReload16(T3_RELOAD);      //设置定时器3的16位重载值
    TIMER3_Run();                     //定时器3开始运行

    //<<AICUBE_USER_TIMER3_INITIAL_BEGIN>>
    // 在此添加用户初始化代码
    //<<AICUBE_USER_TIMER3_INITIAL_END>>
}


////////////////////////////////////////
// 定时器0中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER0_ISR(void) interrupt TMR0_VECTOR
{
    //<<AICUBE_USER_TIMER0_ISR_CODE1_BEGIN>>
    // 在此添加中断函数用户代码printf("KEY Work from KS%02X.\r\n", i);
        static u8 i=0; //LED1每隔1000ms切换1次
        i++;
        if(i>10)
        {
                i=0;
                LED1=!LED1;
                printf_usb("定时器0设定1秒时间到 ! \r\n");
        }
    //<<AICUBE_USER_TIMER0_ISR_CODE1_END>>
}

////////////////////////////////////////
// 定时器1中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER1_ISR(void) interrupt TMR1_VECTOR
{
    //<<AICUBE_USER_TIMER1_ISR_CODE1_BEGIN>>
    // 在此添加中断函数用户代码
        static u8 j=0; //LED2每隔2000ms切换1次
        j++;
        if(j>10)
        {
                j=0;
                LED2=!LED2;
                printf_usb("定时器1设定2秒时间到 ! \r\n");
        }
    //<<AICUBE_USER_TIMER1_ISR_CODE1_END>>
}

////////////////////////////////////////
// 定时器2中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER2_ISR(void) interrupt TMR2_VECTOR
{
    //<<AICUBE_USER_TIMER2_ISR_CODE1_BEGIN>>
    // 在此添加中断函数用户代码
        static u8 k=0; //LED3每隔3000ms切换1次
        k++;
        if(k>10)
        {
                k=0;
                LED3=!LED3;
                printf_usb("定时器2设定3秒时间到 ! \r\n");
        }
    //<<AICUBE_USER_TIMER2_ISR_CODE1_END>>
}

////////////////////////////////////////
// 定时器3中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void TIMER3_ISR(void) interrupt TMR3_VECTOR
{
    //<<AICUBE_USER_TIMER3_ISR_CODE1_BEGIN>>
    // 在此添加中断函数用户代码
        static u8 h=0; //LED4每隔4000ms切换1次
        h++;
        if(h>10)
        {
                h=0;
                LED4=!LED4;
                printf_usb("定时器3设定4秒时间到 ! \r\n");
        }
    //<<AICUBE_USER_TIMER3_ISR_CODE1_END>>
}


//<<AICUBE_USER_FUNCTION_IMPLEMENT_BEGIN>>
// 在此添加用户函数实现代码
//<<AICUBE_USER_FUNCTION_IMPLEMENT_END>>


wuzhengmin 发表于 2026-3-5 11:37:28

下载后一切顺利,USB-CDC也能顺利工作

目前这块老普中 HC6800-ES V2.0 除了按键,特别是外部中断和IO中断实验有点问题,其他都一切正常,可见普中产品的质量

还是很🐮的,毕竟是10年前的产品,翻出来立马能用,厉害!

wuzhengmin 发表于 2026-3-5 11:55:21

16.1-PWM呼吸灯实验-简介

现在我们能输出2中电平,0V 或者高电平5V(3.3V)

我需要输出1.5V ,怎么办?

2条路:芯片有2个办法:1是DAC ,2 是PWM

我们控制PWM的占空比:

wuzhengmin 发表于 2026-3-5 12:09:57


假设频率是1K,占空比是50%   如果是3.3V供电,输出大约就是1.5V

占空比加大,输出电压就大,当然我们还是输出数字信号

本讲主要内容
1.实验介绍
2.硬件设计
3.软件设计
4.实验现象


wuzhengmin 发表于 2026-3-5 12:15:59

Ai8051U系列单片机内部集成了3组可编程计数器阵列(PCA/CCP/PWM)模块可用于软件定时器、外部脉冲捕获、高速脉冲输出和PWM 脉宽调制输出。
PCA内部含有一个特殊的16位计数器,3组PCA模块均与之相连接。

页: 9 10 11 12 13 14 15 16 17 18 [19] 20 21 22 23 24 25 26 27 28
查看完整版本: 学习休眠唤醒遇到的问题:1无法开启休眠 2舍弃一下功能后能进入休眠但无法唤醒