STC单片机利用PCA在扩展外部中断和定时器以及脉宽测量的应用示例
用CCP/PCA功能扩展外部中断的测试程序
- 实验现象说明: 当P1.1口的电平被拉低是产生中断,让P1.0 引脚口上的电平发生反转。
#include "reg51.h"
#include "intrins.h"
typedef unsigned char BYTE;
typedef unsigned int WORD;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P_SW1 = 0xA2;
#define CCP_S0 0x10
#define CCP_S1 0x20
sfr CCON = 0xD8;
sbit CCF0 = CCON^0;
sbit CCF1 = CCON^1;
sbit CR = CCON^6;
sbit CF = CCON^7;
sfr CMOD = 0xD9;
sfr CL = 0xE9;
sfr CH = 0xF9;
sfr CCAPM0 = 0xDA;
sfr CCAP0L = 0xEA;
sfr CCAP0H = 0xFA;
sfr CCAPM1 = 0xDB;
sfr CCAP1L = 0xEB;
sfr CCAP1H = 0xFB;
sfr PCAPWM0 = 0xf2;
sfr PCAPWM1 = 0xf3;
sbit PCA_LED = P1^0;
void PCA_isr() interrupt 7
{
CCF0 = 0;
PCA_LED = !PCA_LED;
}
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
ACC = P_SW1;
ACC &= ~(CCP_S0 | CCP_S1);
P_SW1 = ACC;
CCON = 0;
CL = 0;
CH = 0;
CMOD = 0x00;
CCAPM0 = 0x11;
CR = 1;
EA = 1;
while (1);
}
用CCP/PCA功能实现16位定时器的测试程序
- 实验现象;接在P1.0口上的led灯,每隔一秒钟闪烁一次。
#include "reg51.h"
#include "intrins.h"
#define FOSC 11059200L
#define T100Hz (FOSC / 12 / 100)
typedef unsigned char BYTE;
typedef unsigned int WORD;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P_SW1 = 0xA2;
#define CCP_S0 0x10
#define CCP_S1 0x20
sfr CCON = 0xD8;
sbit CCF0 = CCON^0;
sbit CCF1 = CCON^1;
sbit CR = CCON^6;
sbit CF = CCON^7;
sfr CMOD = 0xD9;
sfr CL = 0xE9;
sfr CH = 0xF9;
sfr CCAPM0 = 0xDA;
sfr CCAP0L = 0xEA;
sfr CCAP0H = 0xFA;
sfr CCAPM1 = 0xDB;
sfr CCAP1L = 0xEB;
sfr CCAP1H = 0xFB;
sfr PCAPWM0 = 0xf2;
sfr PCAPWM1 = 0xf3;
sbit PCA_LED = P1^0;
BYTE cnt;
WORD value;
void PCA_isr() interrupt 7
{
CCF0 = 0;
CCAP0L = value;
CCAP0H = value >> 8;
value += T100Hz;
if (cnt-- == 0)
{
cnt = 100;
PCA_LED = !PCA_LED;
}
}
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
ACC = P_SW1;
ACC &= ~(CCP_S0 | CCP_S1);
P_SW1 = ACC;
CCON = 0;
CL = 0;
CH = 0;
CMOD = 0x00;
value = T100Hz;
CCAP0L = value;
CCAP0H = value >> 8;
value += T100Hz;
CCAPM0 = 0x49;
CR = 1;
EA = 1;
cnt = 0;
while (1);
}
用CCP/PCA的16位捕获模式测脉冲宽度的程序
该示例程序没有验证成功,在外部输入pwm到引脚上,串口并没看到数据。
#include "reg51.h"
#include "intrins.h"
#include <stdio.h>
#define FOSC 11059200L
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P_SW1 = 0xA2;
#define CCP_S0 0x10
#define CCP_S1 0x20
sfr CCON = 0xD8;
sbit CCF0 = CCON^0;
sbit CCF1 = CCON^1;
sbit CR = CCON^6;
sbit CF = CCON^7;
sfr CMOD = 0xD9;
sfr CL = 0xE9;
sfr CH = 0xF9;
sfr CCAPM0 = 0xDA;
sfr CCAP0L = 0xEA;
sfr CCAP0H = 0xFA;
sfr CCAPM1 = 0xDB;
sfr CCAP1L = 0xEB;
sfr CCAP1H = 0xFB;
sfr CCAPM2 = 0xDC;
sfr CCAP2L = 0xEC;
sfr CCAP2H = 0xFC;
sfr PCA_PWM0 = 0xf2;
sfr PCA_PWM1 = 0xf3;
sfr PCA_PWM2 = 0xf4;
sfr AUXR = 0x8E;
sfr T2H = 0xD6;
sfr T2L = 0xD7;
sbit EPCA = IE^6;
BYTE cnt;
DWORD count0;
DWORD count1;
DWORD length;
void UART_init(void)
{
SCON = 0x50;
AUXR |= 0x01;
AUXR &= 0xFB;
T2L = 0xE8;
T2H = 0xFF;
AUXR |= 0x10;
TI=1;
ES = 1;
EA=1;
}
void UART1_SendData(char dat)
{
ES=0;
SBUF=dat;
while(TI!=1);
TI=0;
ES=1;
}
char putchar(char c)
{
UART1_SendData(c);
return c;
}
void main()
{
P0M1 = 0x03;
P0M0 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
ACC = P_SW1;
ACC &= ~(CCP_S0 | CCP_S1);
P_SW1 = ACC;
CCON = 0;
CL = 0;
CH = 0;
CCAP1L = 0;
CCAP1H = 0;
CMOD = 0x09;
CCAPM1 = 0x31;
CR = 1;
EA = 1;
cnt = 0;
count0 = 0;
count1 = 0;
UART_init();
printf("STC15W408AS \n");
printf("TRG!!!\n");
while (1){
if(length > 0)
printf("Pulse_length: %lu\n",length);
length = 0 ;
}
}
void PCA_isr() interrupt 7
{
if (CF)
{
CF = 0;
cnt++;
}
if (CCF1)
{
CCF1 = 0;
count0 = count1;
((BYTE *)&count1)[3] = CCAP1L;
((BYTE *)&count1)[2] = CCAP1H;
((BYTE *)&count1)[1] = cnt;
((BYTE *)&count1)[0] = 0;
length = count1 - count0;
}
}
CCP/PCA输出PWM(6位+7位+8位)的测试程序
通过逻辑分析仪,本示例代码,值采集到了P1.0和P37引脚上的PWM波形,P1.1并没有产生PWM波。
- 采集到P10、P11、P37引脚的占空比:约75%,87.5%、50%,
#include "reg51.h"
#include "intrins.h"
#define FOSC 11059200L
typedef unsigned char BYTE;
typedef unsigned int WORD;
sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;
sfr P_SW1 = 0xA2;
#define CCP_S0 0x10
#define CCP_S1 0x20
sfr CCON = 0xD8;
sbit CCF0 = CCON^0;
sbit CCF1 = CCON^1;
sbit CR = CCON^6;
sbit CF = CCON^7;
sfr CMOD = 0xD9;
sfr CL = 0xE9;
sfr CH = 0xF9;
sfr CCAPM0 = 0xDA;
sfr CCAP0L = 0xEA;
sfr CCAP0H = 0xFA;
sfr CCAPM1 = 0xDB;
sfr CCAP1L = 0xEB;
sfr CCAP1H = 0xFB;
sfr CCAPM2 = 0xDC;
sfr CCAP2L = 0xEC;
sfr CCAP2H = 0xFC;
sfr PCA_PWM0 = 0xf2;
sfr PCA_PWM1 = 0xf3;
sfr PCA_PWM2 = 0xf4;
void main()
{
P0M0 = 0x00;
P0M1 = 0x00;
P1M0 = 0x00;
P1M1 = 0x00;
P2M0 = 0x00;
P2M1 = 0x00;
P3M0 = 0x00;
P3M1 = 0x00;
P4M0 = 0x00;
P4M1 = 0x00;
P5M0 = 0x00;
P5M1 = 0x00;
ACC = P_SW1;
ACC &= ~(CCP_S0 | CCP_S1);
P_SW1 = ACC;
CCON = 0;
CL = 0;
CH = 0;
CMOD = 0x00;
PCA_PWM0 = 0x00;
CCAP0H = CCAP0L = 0x20;
CCAPM0 = 0x42;
PCA_PWM1 = 0x40;
CCAP1H = CCAP1L = 0x20;
CCAPM1 = 0x42;
PCA_PWM2 = 0x80;
CCAP2H = CCAP2L = 0x20;
CCAPM2 = 0x42;
CR = 1;
while (1);
}
|