这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 【STCAi8051U】使用外部脉冲时的PCA的定时器模式例程

共1条 1/1 1 跳转至

【STCAi8051U】使用外部脉冲时的PCA的定时器模式例程

专家
2026-03-16 11:01:43     打赏

以外部脉冲作为时钟的PCA定时器模式下,除了配置CMOD时不一样,其他部分与用系统时钟没有什么不同。本例中Timer0产生脉冲作为PCA的时钟,并设置PCA的计数临界值为10。就是说Timer0每产生10个脉冲时,PCA产生一次中断。体现在IO口上,就是一次电平的变化。Timer0每产生20个脉冲, PCA产生一个脉冲。

以程序代码如下:


// 烧录时钟配置为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  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;
  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
    
    CL = 0x00;
    CH = 0x00;
    CCAPM0 = 0x49; //PCA 模块 0 为 16 位定时器模式
    
    value = T1000HZ;
    CCAP0L = value;
    CCAP0H = value >> 8;
    
    value += T1000HZ;
    CCON |= CR; //启动 PCA 计时器


    EA = 1;
    while (1) {

    }
}


测试输出(黄色的是Timer0的输出,粉色的是PCA的输出,注意:要保证Timer0的输出 P20 短接到PCA的ECI输入端 P12上):

图片2.png

测试结果符合预期。




关键词: 懒猫的学习笔记     Ai8051U     PCA    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]