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; // 计数器清零
    }
}
相关推荐
HQB20266 小时前
EG1198|屹晶微电子 120V 内置 MOS 异步降压 DC‑DC(高性价比)
嵌入式硬件·硬件工程
果壳science7 小时前
张祥前实验如何获取正电荷
笔记·科技·嵌入式硬件·硬件工程·制造
南山电子nscn7 小时前
中科芯CETC汽车电池管理系统BMS进口芯片国产型号替代指南
单片机·汽车·bms
沉淀的.晴天8 小时前
can总线
stm32
桀人8 小时前
认识AT24C02
stm32·单片机·嵌入式硬件
国科安芯9 小时前
星间激光通信终端CANFD控制网络的时延确定性与辐射可靠性
网络·嵌入式硬件·信息与通信·canfd·低轨卫星·商业航天·抗辐射
一直C10 小时前
嵌入式 Linux 驱动开发学习笔记:内核定时器、platform 总线与 I²C 驱动
linux·驱动开发·嵌入式硬件·学习·imx6ull
传感器与混合集成电路10 小时前
150MHz主频、8路DAC与6路PWM:JLH221360伺服控制SIP解析
嵌入式硬件
comyccccc10 小时前
STM32PID控制板设计全解析学习笔记
单片机·嵌入式硬件
碧海银沙音频科技研究院11 小时前
实现炬芯ATS308X的usb cdc 串口IAP 固件升级功能实现
人工智能·嵌入式硬件·深度学习·算法