分频输出2M左右方波,选用T2,此时要求引脚只能配置到P1.0,程序如下:
//分频输出方波
void setup() {
// ===================== P10 配置为硬件时钟输出 =====================
pinMode(10, OUTPUT); // P10 = 引脚10
P1_MOD_OC &= ~(1 << 0); // P10 推挽输出
P1_DIR_PU |= (1 << 0); // 强推挽驱动
// ===================== Timer2 配置 =====================
T2MOD = 0xF0; //C0,D0,E0,F0:都可以
T2CON = 0x00;
C_T2 = 0;
uint16_t div = 6; //分频数
uint16_t reload = 65536 - div;
RCAP2H = (uint8_t)(reload >> 8);
RCAP2L = (uint8_t)reload;
TH2 = RCAP2H;
TL2 = RCAP2L;
// ===================== 开启 T2 时钟输出到 P10 =====================
T2MOD |= (1 << 1); // bT2_CLKO = 1 → 硬件时钟输出
TR2 = 1; // 启动 Timer2
}
void loop() {
// P10 自动持续输出方波,无需代码
}
注意在使用内部晶振时,USB设置要选择USB CODE模式,如图:

|----------|-----|--------|----------------|-------|
| 主频(M) | div | 目标值(M) | 实测值(M) | 误差(%) |
| 内置24 | 6 | 2 | 1.9952~2.0068 | 0.34 |
| 外置24 | 6 | 2 | 1.9974~2.0036 | 0.18 |
| 外置12.288 | 3 | 2.048 | 2.0446~2.0509 | 0.17 |
| 外置24.576 | 6 | 2.048 | 2.0437~2.0521 | 0.21 |
从以上数据表格可以看出,内置24M晶振稳定性能是最差的,这是可以理解的,毕竟是RC振荡,且官方保证精度是2%内。外置24.576M晶振性能也不好,考虑是受该型号单片机24M工作主频的限制,24.576M属于超频使用了。外置晶振24M和12.288M选择的是同一家供应商,指标也一致,但这个误差相当于1700~1800ppm,和官方宣传的10ppm还是有相当差距的。
以TP3057对2.048M时钟要求为例,其边沿跳变时间不大于50ns,高/低电平维持时间不小于160ns。实测图如下,很明显可以看出,完全满足要求。

进一步,同时产生8K的脉冲,其宽度不小于100ns,这里取1us,实测约为1.17us,其宽度小于3个2.048M的脉冲。
// 分频输出方波 (P10) + 8kHz窄脉冲 (P11) ------ SDCC 兼容内联汇编
void setup() {
// ===================== P10 配置 =====================
pinMode(10, OUTPUT);
P1_MOD_OC &= ~(1 << 0);
P1_DIR_PU |= (1 << 0);
// ===================== Timer2 (P10 输出方波) =====================
T2MOD = 0xF0;
T2CON = 0x00;
C_T2 = 0;
uint16_t div = 6;
uint16_t reload = 65536 - div;
RCAP2H = (uint8_t)(reload >> 8);
RCAP2L = (uint8_t)reload;
TH2= RCAP2H;
TL2= RCAP2L;
T2MOD |= (1 << 1);
TR2 = 1;
// ===================== P11 配置 =====================
pinMode(11, OUTPUT);
P1_DIR_PU |= (1 << 1); // P11 强推挽
P1 &= ~(1 << 1); // 初始低电平
// ===================== Timer1 (查询模式) =====================
TMOD &= ~0xF0;
TMOD |= 0x10; // 模式1 (16位)
TH1 = 0xF4;//12.288M为FA,24.576M为F4
TL1 = 0x00;
TR1 = 1;
}
void loop() {
if (TF1) {
TF1 = 0;
TH1 = 0xF4;
TL1 = 0x00;
P1 |= (1 << 1);
delayMicroseconds(1); // 延时约 1 μs(实际可能略长)
P1 &= ~(1 << 1);
}
}