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; // 计数器清零
    }
}
相关推荐
橘为己有4412 分钟前
51单片机:流水灯
单片机·51单片机
蜀黍@猿3 分钟前
ARM 汇编入门(十):标量浮点与 VFP 指令全解析
汇编·arm开发·stm32·mcu
不脱发的程序猿14 分钟前
STM32和VS1053制作电子琴
stm32·单片机·嵌入式硬件·midi·vs1053
Zwawa14 小时前
C语言函数指针与宏实战:从回调、表驱动菜单到X-Macro,讲透嵌入式代码解耦
c语言·单片机·嵌入式
shimly12345615 小时前
(done) 嵌入式硬件电路图 (2) 熟悉常用元器件
嵌入式硬件
Zw-awa18 小时前
C语言函数指针与宏实战:从回调、表驱动菜单到X-Macro,讲透嵌入式代码解耦
stm32
安妮细水长流20 小时前
ad7124
c语言·单片机
花月mmc1 天前
【FPGA】神经网络内容简介预告
嵌入式硬件·深度学习·神经网络·fpga开发
en.en..1 天前
STM32 HAL 库 | 核心知识点整理
单片机·嵌入式硬件
无敌贵点大王1 天前
从寄存器层面重学STM32(9)——DMA理论
stm32·单片机·嵌入式硬件