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; // 计数器清零
    }
}
相关推荐
youcans_2 小时前
【动手学STM32G4】(15)三路互补带死区 PWM 输出
stm32·单片机·嵌入式硬件·pwm·死区
小慧10242 小时前
外部中断与回调函数
stm32·单片机·嵌入式硬件
加斯顿工程师2 小时前
STM32F103C8T6驱动DS18B20温度传感器程序
stm32·单片机·嵌入式硬件
czy87874753 小时前
LwIP 协议栈核心.c 文件依赖关系图
c语言·网络·单片机
猪八戒1.03 小时前
L C D
开发语言·stm32
YouEmbedded3 小时前
解码STM32 看门狗、低功耗与RTC外设
stm32·低功耗·rtc·看门狗·闹钟
YouEmbedded3 小时前
解码模数转换器(ADC)
stm32·adc·电位器adc·ps2摇杆模块adc·adc数据滤波算法·光敏电阻adc
Zeku4 小时前
Linux驱动学习笔记:SPI子系统中的内核线程初始化
stm32·freertos·linux驱动开发·linux应用开发
项目題供诗4 小时前
51单片机入门(四)
单片机·嵌入式硬件·51单片机