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; // 计数器清零
    }
}
相关推荐
不能跑的代码不是好代码2 小时前
STM32窗口看门狗(WWDG)知识点及标准库使用指南
stm32·单片机·嵌入式硬件
bingquan33332 小时前
在 Ghidra 中分析STM32裸机固件
stm32·单片机·嵌入式硬件
羽获飞2 小时前
从零开始学嵌入式之STM32——11.STM32---USART串行通讯
stm32·单片机·嵌入式硬件
宵时待雨4 小时前
STM32笔记归纳9:定时器
笔记·stm32·单片机·嵌入式硬件
逐步前行4 小时前
STM32_新建工程(寄存器版)
stm32·单片机·嵌入式硬件
bai5459364 小时前
STM32 CubeIDE 通过PWM占空比控制舵机角度
stm32·单片机·嵌入式硬件
松涛和鸣6 小时前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
简单中的复杂6 小时前
【避坑指南】RK3576 Linux SDK 编译:解决 Buildroot 卡死在 host-gcc-final 的终极方案
linux·嵌入式硬件
上海合宙LuatOS7 小时前
LuatOS核心库API——【audio 】
java·网络·单片机·嵌入式硬件·物联网·音视频·硬件工程
Hhh __灏7 小时前
stm32的SRAM内存不足如何分析和优化?堆栈空间如何优化?
单片机