个人感觉,这种高速脉冲模式与定时器模式没太大区别。
程序代码如下(产生40KHz的脉冲):
// 烧录时钟配置为24MHz
#include "../comm/Ai8051U.h"
#include "intrins.h"
#include "stdio.h"
#define FOSC 24000000UL //定义主时钟
#define BRT (65536 - (FOSC / 115200) / 4)
#define Timer0_Reload (FOSC / 2400) //Timer 0
//// 最后的1000,是设置频率。除以2是因为两次中断才会产生一个脉冲
//// FOSC / 12 需要配合CMOD的设置,匹配PCA时钟设置
//#define T1000HZ (FOSC / 12 / 2 / 1000)
#define T1000HZ 10
// 高速脉冲
#define T40KHZ (FOSC / 2 / 40000)
#define CF 0x80
#define CR 0x40
#define CCF0 0x01
// 测试用输出引脚
// P2.0链接P1.3,P2.0输出的脉冲信号,由可编程计数器阵列PCA0由P1.3引脚捕获,作为对比,由P2.1输出
sbit TEST_OUT = P2^0;
sbit PCA0_OUT = P2^1;
unsigned int value;
// timer0初始化函数。本利中使用定时器0产生的1000Hz信号作为PCA的外部脉冲输入信号,需要短接
void Timer0_init(void) {
TR0 = 0; //停止计数
ET0 = 1; //允许中断
TMOD &= ~0x03; // 16位自动重装模式
TMOD &= ~T0_CT; // 定时器模式
INTCLKO &= ~T0CLKO; //不输出时钟
AUXR |= T0x12; //1T mode
TH0 = (unsigned char)((65536UL - Timer0_Reload) / 256);
TL0 = (unsigned char)((65536UL - Timer0_Reload) % 256);
TR0 = 1; //开始运行
}
// timer0中断函数,目的是产生脉冲信号给PCA
// 信号通过P1.3,输出给PCA
void timer0_int (void) interrupt 1 {
// P20电平翻转
P20 = ~P20;
}
// 测试使用Timer2作为串口的波特率发生器
void Timer2Init(void) {
T2L = BRT;
T2H = BRT >> 8;
//S1BRT = 1; // S1BRT:串口1的波特率发生器选择位: 0-选择定时器1作为波特率发生器;1-选择定时器2作为波特率发生器(默认)
//T2x12 = 1;
//T2R = 1;
AUXR |= S1BRT | T2x12 | T2R;
}
// 串口P3.6(RXD),P3.7(TXD)
////---------------------------------------------------------------
//void Uart1Isr() interrupt 4 {
// if (TI) {
// TI = 0;
// busy1 = 0;
// }
// if (RI) {
// RI = 0;
// buffer1[wptr1++] = SBUF;
// wptr1 &= 0x0f;
// }
//}
void Uart1Init() {
SCON = 0x50; //
P_SW1 |= 0x40; // 选择P3.6,P3.7,因为擎天柱开发板上不提供P3.0,P3.1引脚
}
void Uart1Send(char dat) {
// 送出要发送的数据
SBUF = dat;
// 等待串口发送完成
while (TI==0);
TI=0; // 清除标志
}
void Uart1SendStr(char *p) {
while (*p) {
Uart1Send(*p++);
}
}
// 可编程计数器模块中断
void PCA_Isr() interrupt 7 {
// 清除中断标志
CCON &= ~CCF0;
CCAP0L = value;
CCAP0H = value >> 8;
//value += T1000HZ;
value += T40KHZ;
PCA0_OUT = !PCA0_OUT; //测试端口
}
void main(void) {
int i = 0;
char buf[64]={'\0'};
// 允许访问扩展的特殊寄存器, XFR
P_SW2 |= EAXFR;
//(32 位模式请使用这句,注释下一句 )
// P_SW2 |= 0x80; // 允许访问扩展的特殊寄存器, XFR
//(8 位模式请使用这句,注释上一句 )
WTST = 0; // 设置取程序代码等待时间,
// 赋值为 0 表示不等待,程序以最快速度运行
CKCON = 0; // 设置访问片内的 xdata 速度,
// 赋值为 0 表示用最快速度访问,不增加额外的等待时间
P0M0 = 0x00; P0M1 = 0x00; P1M0 = 0x00; P1M1 = 0x00;
P2M0 = 0x00; P2M1 = 0x00; P3M0 = 0x00; P3M1 = 0x00;
P4M0 = 0x00; P4M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00;
// // 初始化定时器0,定时周期1000Hz
// Timer0_init();
// 初始化定时器2,给串口1做波特率发生器用
Timer2Init();
// 初始化串口1
Uart1Init();
Uart1SendStr("Start main ......\r\n");
CCON = 0x00;
// CMOD设置:
// B7 = 0 :空闲模式下 PCA 继续计数
// B6 - B5(CCP_S) = 00 :ECI-P1.2 、 CCP0 - P1.3、 CCP1 - P1.4、CCP2 - P1.1
// B4 - B1(CPS) = 0011 :PCA 时钟为外部时钟
// B0= 1 :使能 PCA 计数器溢出中断
//CMOD = 0x00; //PCA 时钟为系统时钟 / 12
//CMOD = 0x06; //PCA 时钟为系统时钟 / 12
CMOD = 0x08; //PCA 时钟为系统时钟
CL = 0x00;
CH = 0x00;
//CCAPM0 = 0x49; //PCA 模块 0 为 16 位定时器模式
// B3(MAT0) : 允许/禁止PCA0模块的匹配功能
// B2(TOG0) : 允许/禁止PCA0模块的高速脉冲功能
// B0(ECCF0) : 允许/禁止PCA0模块的匹配捕获中断
CCAPM0 = 0x4d; //PCA 模块 0 为 16 位定时器模式,输出高速脉冲
value = T40KHZ;
CCAP0L = value;
CCAP0H = value >> 8;
value += T40KHZ;
CCON |= CR; //启动 PCA 计时器
EA = 1;
while (1) {
}
}程序运行效果(黄色信号来自P13,粉色信号来自P21):

二者频率一致,只不过一个来自软件的输出,一个是来自硬件的输出,可以看到有延迟,1.67微妙,应该是软件代码带来的延迟。
我要赚赏金
