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; // 计数器清零
}
}