## STC15W408AS PCA计数器实现脉宽捕获
**写在前头:1、主函数只完成PCA模块捕获功能,串口通信功能请复制下面函数块;2、主函数中包含的reg52.h文件较keil51自带有所增加,请注意区别和替换**
/*
//MCU:STC15W408AS
//功能:用PCA模块实现PWM脉宽测量(修改后亦可测量脉冲周期)
//Date:2021/06/22
*/
#include "reg52.h"
#include "intrins.h"
#include "usart.h"
#define FOSC 22118400L //主频:22.1184MHz
#define CCP_S0 0x10
#define CCP_S1 0x20
#define PLUSE_T (FOSC/12/1000) //12T模式
// time_p =(uint)(temp*1000.0/PLUSE_T); //将计数器中值转换为十进制时间数值,单位为us
uint temp=0; //存储信号长度
uint time_p = 0;
sbit P11 = P1^1;
//PCA脉宽捕获初始化
void PCA_Init()
{
ACC = P_SW1;
ACC &= ~(CCP_S0|CCP_S1);
P_SW1 = ACC; //PCA捕获端口IO映射,第一组IO
CCON = 0x00; //初始化PCA控制器
CL = 0;
CH = 0;
CCAP0L = 0; //此脉宽捕获功能中未用到
CCAP0H = 0; //此脉宽捕获功能中未用到
CMOD = 0x00; //设置PCA时钟源为系统时钟 SYSCLK/12(12分频),且禁止PCA计数溢出中断
// CCAPM0 = 0x21; //PCA模块0为16位捕获模式(上升沿捕获,且产生捕获中断)
// CCAPM0 = 0x11; //PCA模块0为16位捕获模式(下降沿捕获,且产生捕获中断)
CCAPM0 = 0x31; //PCA模块0为16位捕获模式(上升沿/下降沿 捕获,且产生捕获中断)
CR = 0; //禁止PCA定时器工作
EA = 1;
}
void PCA_isr() interrupt 7 using 1 //PCA脉冲捕获中断响应处理函数
{
if(CCF0) //PCA模块0中断标志位 ,当出现匹配或捕获时,该位由硬件置位,必须软件清0
{
CCF0 = 0; //清楚中断标志位
if (P11 == 1) //CCP0模块引脚P1.1捕获,若为上升沿捕获
{
CL = 0; //PCA定时器低字节,直接清零 PCA计数器值(若PCA计数器还需用到定时功能,
//请通过CCAPxL转存该值)
CH = 0; //PCA定时器高字节,直接清零 PCA计数器值(若PCA计数器还需用到定时功能,
//请通过CCAPxH转存该值)
temp = 0; //计数值暂存变量(16位长度)
CR = 1; //启动PCA定时器计数
}
else //若为下降沿捕获
{
CR = 0; //关闭PCA定时器
temp = CL; //暂存低8位
temp |= CH<<8; //暂存高8位
CL = 0; //PCA定时器低字节,直接清0 PCA计数器值(若PCA计数器还需用到定时功能,
//请通过CCAPxL转存该值)
CH = 0; //PCA定时器高字节,直接清0 PCA计数器值(若PCA计数器还需用到定时功能,
//请通过CCAPxH转存该值)
}
}
}
void main()
{
Uart_Init(115200); //串口初始化
PCA_Init(); //PCA模块捕获功能初始化
while(1)
{
time_p =(uint)(temp*1000.0/PLUSE_T); //将计数器中值转换为十进制时间数值,单位为us
SendData(0xFF); //数据引导标志
SendData((time_p>>8)&0xff); //高8位在前
SendData(time_p&0xff); //低8位在后
}
}
//一下为USART1功能函数块 usart.c(请另建文档保存,且被主函数包括含)
#include "usart.h"
//sfr AUXR = 0x8e; //辅助寄存器
sfr T2H = 0xd6; //
sfr T2L = 0xd7;
bit busy;
uint Rdata; //receiver buf
void Uart_Init(unsigned long BAUD) //8位MCU传递大于65536的数值需用4个字节
{
#if (PARITYBIT==NONE_PARITY)
SCON = 0x50; //8位可变波特率
#elif ((PARITYBIT==ODD_PARITY)||(PARITYBIT==EVEN_PARITY)||(PARITYBIT==MARK_PARITY))
SCON = 0xda;
#elif (PARITYBIT==SPACE_PARITY)
SCON=0xd2;
#endif
EA = 0;
T2L = (65536 - (FOSC/4/BAUD)); //设置波特率重装值
T2H = (65536 - (FOSC/4/BAUD))>>8;
AUXR = 0x14; //设置 T2为1T模式,并启动定时器2
AUXR |=0x01; //选定定时器2为串口1的波特率发生器
ES = 1; //使能串口1中断
EA = 1; //打开总中断
}
/*.................
USART中断服务程序
.................*/
void Uart() interrupt 4 using 1
{
if(RI) //接收标志位
{
Rdata = SBUF; //取出接收到的
RI = 0;
}
if(TI)
{
TI = 0; //clear TI flag
busy = 0; //clear busy flag
}
}
/*................
Uart发送字节数据
.................*/
void SendData(BYTE dat)
{
while(busy); //wait for the last data send over
ACC = dat; //获取校验位P(PSW.0)
if(P)
{
#if (PARITYBIT == ODD_PARITY)
TB8 = 0;
#elif(PARITYBIT == EVEN_PARITY)
TB8 = 1; //
#endif
}
else
{
#if(PARITYBIT==ODD_PARITY)
TB8 = 1;
#elif(PARITYBIT==EVEN_PARITY)
TB8 = 0;
#endif
}
busy = 1;
SBUF = ACC; //写数据到UART数据寄存器
}
/*.............
发送字符串
...............*/
void SendString(char *s)
{
while(*s)
{
SendData(*s++); //发送当前字符
}
}
//续2:usart.h文件(请另建文档保存,且被主函数包含)
#ifndef _USART_H
#define _USART_H
#include "reg52.h"
#include "stdio.h"
//typedef unsigned char BYTE;
//typedef unsigned int WORD;
#define uchar unsigned char
#define uint unsigned int
#define FOSC 22118400L //system frequency
//#define BAUD 115200 //baud RATE 115200 bps,由于函数采用参数赋值波特率,这里屏蔽波特率宏定义
#define NONE_PARITY 0 //non chack
#define ODD_PARITY 1 //odd chack
#define EVEN_PARITY 2 //even chack
#define MARK_PARITY 3 //mark chack
#define SPACE_PARITY 4 //block chack
#define PARITYBIT EVEN_PARITY //slect even_parity
//void Uart_Init(); //原串口初始化函数没有形参输入
void Uart_Init(unsigned long BAUD); //无符号长整型数据,4字节 0~(2^32-1)
void SendData(BYTE dat);
void SendString(char *s);
#endif
//续3:若编译报错,请将一下reg52.h头文件替换原头文件
/*--------------------------------------------------------------------------
REG52.H
Header file for generic 80C52 and 80C32 microcontroller.
Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.
All rights reserved.
--------------------------------------------------------------------------*/
#ifndef __REG52_H__
#define __REG52_H__
/* BYTE Registers */
sfr P0 = 0x80; //PORT0
sfr P1 = 0x90; //PORT1
sfr P2 = 0xA0; //PORT2
sfr P3 = 0xB0; //PORT3
sfr PSW = 0xD0;
sfr ACC = 0xE0; //累加器
sfr B = 0xF0;
sfr SP = 0x81;
sfr DPL = 0x82;
sfr DPH = 0x83;
sfr PCON = 0x87;
sfr TCON = 0x88;
sfr TMOD = 0x89;
sfr TL0 = 0x8A;
sfr TL1 = 0x8B;
sfr TH0 = 0x8C;
sfr TH1 = 0x8D;
sfr IE = 0xA8;
sfr IP = 0xB8;
sfr SCON = 0x98;
sfr SBUF = 0x99;
/* 8052 Extensions */
sfr T2CON = 0xC8;
sfr RCAP2L = 0xCA;
sfr RCAP2H = 0xCB;
sfr TL2 = 0xCC;
sfr TH2 = 0xCD;
/* self add 2020/08/20 */
//GPIO_MODE SFR
sfr P0M1 = 0x93; //93H
sfr P0M0 = 0x94; //94H
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P3M1 = 0xB1;
sfr P3M0 = 0xB2;
/* BIT Registers */
/* PSW */
sbit CY = PSW^7;
sbit AC = PSW^6;
sbit F0 = PSW^5;
sbit RS1 = PSW^4;
sbit RS0 = PSW^3;
sbit OV = PSW^2;
sbit P = PSW^0; //8052 only
/* TCON */
sbit TF1 = TCON^7;
sbit TR1 = TCON^6;
sbit TF0 = TCON^5;
sbit TR0 = TCON^4;
sbit IE1 = TCON^3;
sbit IT1 = TCON^2;
sbit IE0 = TCON^1;
sbit IT0 = TCON^0;
/* IE */
//sfr IE = 0XA8; //中断允许寄存器(可位寻址)
sfr IE2 = 0xAF; //中断允许寄存器(不可位寻址),T2中断允许控制位:ET2
sbit EA = IE^7; //CPU总中断允许位
sbit ELVD =IE^6; //低压检测中断允许位
sbit ET2 = IE^5; //8052 only
//sbit EADC = IE^5 //A/D转换中断允许位
sbit ES = IE^4; //串口1中断允许位
sbit ET1 = IE^3; //定时/计数器1溢出中断允许位
sbit EX1 = IE^2; //外部中断1中断允许位
sbit ET0 = IE^1; //定时/计数器0溢出中断允许位
sbit EX0 = IE^0; //外部中断0中断允许位
/* IP */
//sfr IP = 0XB8; //中断优先级控制寄存器(可位寻址)
sbit PPCA = IP^7; //PCA中断优先级控制位
sbit PLVD = IP^6; //低压检测中断优先级控制位
sbit PADC = IP^5; //A/D转换中断优先级控制位
//sbit PT2 = IP^5;//STC15系列 定时器2不能进行优先级设置
sbit PS = IP^4; //串口1中断优先级控制位
sbit PT1 = IP^3; //定时器1中断优先级控制位
sbit PX1 = IP^2; //外部中断1优先级控制位
sbit PT0 = IP^1; //定时器0中断优先级控制位
sbit PX0 = IP^0; //外部中断0优先级控制位
/* P3 */
sbit RD = P3^7;
sbit WR = P3^6;
sbit T1 = P3^5;
sbit T0 = P3^4;
sbit INT1 = P3^3;
sbit INT0 = P3^2;
sbit TXD = P3^1;
sbit RXD = P3^0;
/* SCON */
sbit SM0 = SCON^7;
sbit SM1 = SCON^6;
sbit SM2 = SCON^5;
sbit REN = SCON^4;
sbit TB8 = SCON^3;
sbit RB8 = SCON^2;
sbit TI = SCON^1;
sbit RI = SCON^0;
/* P1 */
sbit T2EX = P1^1; // 8052 only
sbit T2 = P1^0; // 8052 only
/* T2CON */
sbit TF2 = T2CON^7;
sbit EXF2 = T2CON^6;
sbit RCLK = T2CON^5;
sbit TCLK = T2CON^4;
sbit EXEN2 = T2CON^3;
sbit TR2 = T2CON^2;
sbit C_T2 = T2CON^1;
sbit CP_RL2 = T2CON^0;
/* CCP/PCA */
sfr CCON = 0xD8; //PCA 控制寄存器
sbit CCF0 =CCON^0; //PCA模块0中断标志位
sbit CCF1 =CCON^1; //PCA模块1中断标志位
sbit CR = CCON^6; //PCA定时器运行控制寄存器
sbit CF = CCON^7; //PCA定时器溢出寄存器
sfr CMOD = 0xD9; //PCA模式寄存器
sfr CL =0xE9; //PCA定时器低字节
sfr CH =0xF9; //PCA定时器高字节
sfr CCAPM0=0xDA; //PCA模块0模式寄存器
sfr CCAP0L=0xEA; //PCA模块0捕获寄存器LOW
sfr CCAP0H=0xFA; //PCA模块0捕获寄存器HIGH
sfr CCAPM1 =0xDB; //PCA模块1模式寄存器
sfr CCAP1L=0xEB; //PCA模块1捕获寄存器LOW
sfr CCAP1H=0xFB; //PCA模块1捕获寄存器HIGH
sfr CCAPM2 =0xDC; //PCA模块2模式寄存器
sfr CCAP2L=0xEC; //PCA模块2捕获寄存器LOW
sfr CCAP2H=0xFC; //PCA模块2捕获寄存器HIGH
sfr PCA_PWM0=0xF2; //PCA模块0的PWM寄存器
sfr PCA_PWM1=0xF3; //PCA模块1的PWM寄存器
sfr PCA_PWM2=0xF4; //PCA模块2的PWM寄存器
sfr P_SW1 = 0xA2; //外设功能切换寄存器1
sfr P_SW2 = 0xBA; //外设功能切换寄存器2
sfr AUXR = 0x8E; //辅助寄存器
typedef unsigned char uchar;
typedef unsigned char BYTE;
typedef unsigned int uint;
typedef unsigned long DWORD;
//#define DWORD unsigned long
#endif
STC15W408AS PCA模块实现脉宽捕获
最新推荐文章于 2023-10-02 08:20:07 发布
本文详细介绍了如何使用STC15W408AS单片机的PCA模块进行脉宽捕获,包括PCA初始化、中断处理和主函数中的脉宽计算。通过PCA计数器,可以测量PWM脉冲的宽度或周期,适用于实时控制和信号分析应用。
摘要由CSDN通过智能技术生成