SDCC+Ai8051U 中断点灯

Ai8051U 的中断模式 可以选择1T或者12T!

芯片手册: 嘉立创 STC Ai8051U

(P879)

1T模式

cpp 复制代码
// 40MHZ / 1 = 40MHz  -> 1 tick = 0.025us = 25ns
// min 16 bit timer | 25ns <-> 1.638125ms(1628125ns)
void Timer0_Init(void) // 1ms@40MHz  -- 1T
{
    AUXR |= T0x12; // 定时器时钟1T模式(原本12T快12倍 就是1T 不是12*12=144T  -- 如快4T就是3T)
    TMOD &= 0xF0; // 设置定时器模式
    TMOD |= 0x01; // 定时器0,模式1,16位计数器
    // 1,000,000us / 25us 就是1ms需要的计数值
    TH0 = (65536 - (1000000/25)) >> 8; // 设置定时初值,高8位
    TL0 = (65536 - (1000000/25)) & 0xFF; // 设置定时初值,低8位
    ET0 = 1; // 允许定时器0中断
    TR0 = 1; // 启动定时器0
    EA = 1;  // 全局中断使能
}

12T模式

cpp 复制代码
// 40MHZ /12 ~= 3.33MHz  -> 1 tick = 0.3us = 300ns
// min 16 bit timer | 300ns <-> 19.66ms(19,660,800ns)
void Timer0_Init(void) // 1us@40MHz  -- 12T
{
    // 可以查手册后 进行对位与操作
    // AUXR &= ~T0x12;
    TMOD &= 0xF0; // 设置定时器模式
    TMOD |= 0x01; // 定时器0,模式1,16位计数器
    TH0 = (65536 - (1000/300)) >> 8; // 设置定时初值,高8位
    TL0 = (65536 - (1000/300)) & 0xFF; // 设置定时初值,低8位
    ET0 = 1; // 允许定时器0中断
    TR0 = 1; // 启动定时器0
    EA = 1;  // 全局中断使能
}

随机灯/呼吸灯(12T)

cpp 复制代码
#include <Ai8051U.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>


// ---自定义变量---
uint16_t count0 = 0;
uint16_t RED_Count = 100;
uint16_t GREEN_Count = 100;
uint16_t BLUE_Count = 100;
// --------------

#define HIRC                    40000000UL
#define FOSC                    40000000UL
#define SYSCLK                  FOSC
#define MAIN_Fosc               FOSC


void delay_us(uint16_t us)
{
    do
    {
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
    } while (--us);
}
 
 
void delay_ms(uint16_t ms)
{
    uint16_t i;
 
    do
    {
        i = MAIN_Fosc / 10000;
        while (--i);
    } while (--ms);
}

// 40MHZ /12 ~= 3.33MHz  -> 1 tick = 0.3us = 300ns
// min 16 bit timer | 300ns <-> 19.66ms(19,660,800ns)
void Timer0_Init(void) // 1us@40MHz  -- 12T
{
    TMOD &= 0xF0; // 设置定时器模式
    TMOD |= 0x01; // 定时器0,模式1,16位计数器
    TH0 = (65536 - (1000/300)) >> 8; // 设置定时初值,高8位
    TL0 = (65536 - (1000/300)) & 0xFF; // 设置定时初值,低8位
    ET0 = 1; // 允许定时器0中断
    TR0 = 1; // 启动定时器0
    EA = 1;  // 全局中断使能
}

void main(void)
{
    // 配置 P2 端口的模式寄存器 0(P2M0)为全 0xff,配合下一行的 P2M1 配置,
    // 将 P2 口的 8 个引脚全部设置为准双向输入模式(也叫通用 IO 输入模式)
    P2M0 = 0xff; // 
    P2M1 = 0x00; // 
    WTST = 0x00; // 关闭看门狗
    P2 = 0x00; // 初始状态
    delay_ms(500); // 延时 500ms
    Timer0_Init(); // 初始化定时器0
    while(1)
    {
        // 呼吸灯效果
        for(uint16_t i=0; i<2000; i++)
        {
            if(i < 1000)
            {
                RED_Count = i;
                GREEN_Count = i;
                BLUE_Count = i;
            }
            else
            {
                RED_Count = 2000 - i;
                GREEN_Count = 2000 - i;
                BLUE_Count = 2000 - i;
            }
            delay_us(50);
        }

        // 生成随机颜色值 -- 种子数 不用设置,以免报错
        // RED_Count = rand() % 1000;   // 红色分量,范围 0-999
        // GREEN_Count = rand() % 1000; // 绿色分量,范围 0-999
        // BLUE_Count = rand() % 1000;  // 蓝色分量,范围 0-999
        // delay_ms(50);
    }
}

void Timer0_ISR(void) __interrupt(1)
{
    // 每次进入中断时,重新加载定时器初值
    TH0 = (65536 - (1000/300)) >> 8; // 设置定时初值,高8位
    TL0 = (65536 - (1000/300)) & 0xFF; // 设置定时初值,低8位
    count0++; // 每次中断,计数器加1
    if(count0 < BLUE_Count) 
    {
        P21 = 1; // 切换 P2.0 的状态
    }
    else
    {
        P21 = 0; // 切换 P2.0 的状态
    }
    
    if(count0 < GREEN_Count) 
    {
        P20 = 1; // 切换 P2.0 的状态
    }
    else
    {
        P20 = 0; // 切换 P2.0 的状态
    }

    if(count0 < RED_Count)
    {
        P22 = 1; // 切换 P2.0 的状态
    }
    else
    {
        P22 = 0; // 切换 P2.0 的状态
    }

    if(count0 >= 1000) 
    {
        count0 = 0; // 计数器清零
    }
}

闪烁灯(1T)

cpp 复制代码
#include <Ai8051U.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>


// ---自定义变量---
uint16_t count0 = 0;
// --------------

#define HIRC                    40000000UL
#define FOSC                    40000000UL
#define SYSCLK                  FOSC
#define MAIN_Fosc               FOSC


void delay_us(uint16_t us)
{
    do
    {
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
        __asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");__asm__("nop");
    } while (--us);
}
 
 
void delay_ms(uint16_t ms)
{
    uint16_t i;
 
    do
    {
        i = MAIN_Fosc / 10000;
        while (--i);
    } while (--ms);
}

// 40MHZ / 1 = 40MHz  -> 1 tick = 0.025us = 25ns
// min 16 bit timer | 25ns <-> 1.638125ms(1628125ns)
void Timer0_Init(void) // 1ms@40MHz  -- 1T
{
    AUXR |= T0x12; // 定时器时钟1T模式(原本12T快12倍 就是1T 不是12*12=144T  -- 如快4T就是3T)
    TMOD &= 0xF0; // 设置定时器模式
    TMOD |= 0x01; // 定时器0,模式1,16位计数器
    // 1,000,000us / 25us 就是1ms需要的计数值
    TH0 = (65536 - (1000000/25)) >> 8; // 设置定时初值,高8位
    TL0 = (65536 - (1000000/25)) & 0xFF; // 设置定时初值,低8位
    ET0 = 1; // 允许定时器0中断
    TR0 = 1; // 启动定时器0
    EA = 1;  // 全局中断使能
}

void main(void)
{
    // 配置 P2 端口的模式寄存器 0(P2M0)为全 0xff,配合下一行的 P2M1 配置,
    // 将 P2 口的 8 个引脚全部设置为准双向输入模式(也叫通用 IO 输入模式)
    P2M0 = 0xff; // 
    P2M1 = 0x00; // 
    WTST = 0x00; // 关闭看门狗
    P2 = 0x00; // 初始状态
    delay_ms(500); // 延时 500ms
    Timer0_Init(); // 初始化定时器0
    while(1)
    {

    }
}

void Timer0_ISR(void) __interrupt(1)
{
    // 每次进入中断时,重新加载定时器初值
    TH0 = (65536 - (1000000/25)) >> 8; // 设置定时初值,高8位
    TL0 = (65536 - (1000000/25)) & 0xFF; // 设置定时初值,低8位
    count0++;
    if (count0 >= 1000) // 1秒钟到达
    {
        P2 ^= 0x01; // 翻转 P2 端口的所有引脚状态
        count0 = 0; // 计数器清零
    }
}
相关推荐
AOI小白新手上路7 小时前
韦东山 01_ARM架构与编程_2-1_处理器的区分MCU_MPU_AP_内容总结
嵌入式硬件
ysu_03147 小时前
TinyML 模型部署:从 Edge Impulse 到 STM32F103
驱动开发·stm32·嵌入式硬件·mcu·硬件架构·硬件工程·dsp开发
zjxtxdy9 小时前
SPI通信协议
笔记·单片机
恒锐丰科技林技术员12 小时前
EG1196S:高压宽输入降压 DC‑DC 芯片,电动车工业电源的优选方案
经验分享·嵌入式硬件·硬件工程
>Andre<13 小时前
UFS5.0标准中文全译·卷一:范围、术语与架构
android·linux·嵌入式硬件
剑指offer.13 小时前
ARM裸机开发-点亮LED灯
linux·服务器·嵌入式硬件
朝发如雪13 小时前
快速掌握单片机基础(8)(内存映射与启动寻址方式)(编译工具链与构建流程)(C语言操作寄存器)
单片机
糖糖单片机设计14 小时前
基于STM32的电子密码锁设计与实现(矩阵键盘+防拆检测+GSM远程报警)
人工智能·stm32·单片机·嵌入式硬件
cyl122407114 小时前
2026年10月嵌入式培训指南:在“AI+嵌入式“爆发前夜,如何选择你的职业跳板?
人工智能·嵌入式硬件
充哥单片机设计14 小时前
【STM32开源项目】智能家电控制系统
stm32·单片机·嵌入式硬件·毕业设计·智能家电控制·家电控制