【普中 51-Ai8051 开发攻略】-- 第 20 章 输入捕获实验

(1)实验平台:

普中 51-Ai8051 开发板https://item.taobao.com/item.htm?abbucket=17&id=1026052331067(2)资料下载 :普中科技-各型号产品资料下载链接


在学习 PWM 呼吸灯实验时, 我们知道 Ai8051U 系列单片机内部集成了 3 组可编程计数器阵列(PCA/CCP/PWM) 模块, 可用于软件定时器、 外部脉冲捕获、 高速脉冲输出和 PWM 脉宽调制输出。 本章我们来学习 PCA 的外部脉冲捕获功能。 本章分为如下几部分内容:

[20.1 实验介绍](#20.1 实验介绍)

[20.1.1 实验简介](#20.1.1 实验简介)

[20.1.2 实验目的](#20.1.2 实验目的)

[20.2 硬件设计](#20.2 硬件设计)

[20.3 软件设计](#20.3 软件设计)

[20.3.1 创建和配置工程](#20.3.1 创建和配置工程)

[20.3.1.1 GPIO 配置](#20.3.1.1 GPIO 配置)

[20.3.1.2 配置 UART1](#20.3.1.2 配置 UART1)

[20.3.1.3 配置 PCA 模块](#20.3.1.3 配置 PCA 模块)

[20.3.1.4 生成工程](#20.3.1.4 生成工程)

[20.3.2 添加用户驱动代码](#20.3.2 添加用户驱动代码)

[20.3.2.1 pca.h 文件](#20.3.2.1 pca.h 文件)

[20.3.2.2 pca.c 文件](#20.3.2.2 pca.c 文件)

[20.3.2.3 main.c 文件](#20.3.2.3 main.c 文件)

[20.4 实验现象](#20.4 实验现象)


20.1 实验介绍

20.1.1 实验简介

要使一个 PCA 模块工作在捕获模式, 寄存器 CCAPMn 中的 CAPNn 和 CAPPn 至少有一位必须置 1(也可两位都置 1)。 PCA 模块工作于捕获模式时, 对模块的外部 CCPO/CCP1/CCP2 管脚的输入跳变进行采样。 当采样到有效跳变时, PCA 控制器立即将 PCA 计数器 CH 和 CL 中的计数值装载到模块的捕获寄存器中 CCAPnL 和CCAPnH, 同时将 CCON 寄存器中相应的 CCFn 置 1。 若 CCAPMn 中的 ECCFn 位被设置为 1, 将产生中断。 由于所有 PCA 模块的中断入口地址是共享的, 所以在中断服务程序中需要判断是哪一个模块产生了中断, 并注意中断标志位需要软件清零。

PCA 模块工作于捕获模式的结构图如下所示:

PCA 模块管脚分布图如下所示:

20.1.2 实验目的

使用 PCA 模块 0 检测该通道低电平时间, 即 K1 键按下后松开, 串口助手输出检测低电平时间。

20.2 硬件设计

本实验使用到硬件资源如下:

(1) GPIO

(2) UART1 串口

(3) USB 转 TTL 模块

相关电路在前面章节已经介绍过, 此处省略。

20.3 软件设计

20.3.1 创建和配置工程

按照前面章节内容创建一份新工程, 并命名为 17-input_cap, 如下图所示:

20.3.1.1 GPIO 配置

使能端口和时钟, 将 P30 和 P31 管脚分配为 UART1, 并使能 UART1, 使能 PCA0模块, 其对应 P20 管脚。 如下图所示:

20.3.1.2 配置 UART1

在 UART1 的参数设置界面中, 可选择"与 printf 函数关联" , 这样就可以非常方便的使用 printf 输出调试结果信息。 如下图所示:

20.3.1.3 配置 PCA 模块

将 PCA 时钟源设置为系统时钟的 4 分频, 初始值为 0,16 位捕获输入模式,下降沿捕获, 使能周期中断的目的是考虑对低电平计数出现溢出时的计算, 使能模块 0 中断。 如下图所示:

20.3.1.4 生成工程

配置完成后, 按下代码生成按钮, 自动创建工程, 系统开始生成初始化代码。生成工程文件目录如下图所示:

PCA 模块配置代码自动生成为 pca.c 文件中。

20.3.2 添加用户驱动代码

20.3.2.1 pca.h 文件

cpp 复制代码
extern u16 CH0_CAPTURE_STA; //输入捕获的状态
extern u16 CH0_CAPTURE_VAL; //输入捕获值

20.3.2.2 pca.c 文件

cpp 复制代码
u16 CH0_CAPTURE_STA; //输入捕获状态 
u16 CH0_CAPTURE_VAL;//输入捕获值

////////////////////////////////////////
// PCA中断服务程序
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void PCA_ISR(void) interrupt PCA_VECTOR
{
    //<<AICUBE_USER_PCA_ISR_CODE1_BEGIN>>
    if((CH0_CAPTURE_STA&0x8000)==0) //还未成功捕获
    {
        // 在此添加中断函数用户代码
        if (PCA_CheckCounterFlag())         //判断PCA模组计数器溢出中断
        {
            PCA_ClearCounterFlag();         //清除PCA模组计数器溢出中断标志
            
            if(CH0_CAPTURE_STA&0X4000)//捕获到了低电平
			{
				if((CH0_CAPTURE_STA&0x3fff)==0x3fff) //低电平时间太长
				{
					CH0_CAPTURE_STA|=0x8000; //标志一次捕获成功
					CH0_CAPTURE_VAL=0xffff;
				}
				else
				{
					CH0_CAPTURE_STA++;
				}
			}
        }

        if (PCA_CheckCCF0Flag())            //判断PCA模块0中断
        {
            PCA_ClearCCF0Flag();            //清除PCA模块0中断标志
            
            if(CH0_CAPTURE_STA&0X4000)//捕获到了高电平
			{
				CH0_CAPTURE_STA|=0x8000; //成功捕获一次低电平
				CH0_CAPTURE_VAL=PCA_ReadC0Capture();
				PCA_SetC0AsCaptureNegMode();//设置下降沿捕获
			}
			else
			{
				CH0_CAPTURE_STA=0;
				CH0_CAPTURE_VAL=0;
				CH0_CAPTURE_STA|=0x4000; //捕获到低电平标志
				PCA_Stop();
				PCA_SetCounter(0); //设置PCA模组计数初始值
				PCA_SetC0AsCapturePosMode(); //设置上升沿捕获
				PCA_Run();
			}
            
    //      PCA_ReadC0Capture();            //读取PCA模块0的16位捕获值
        }
    }
    
    //<<AICUBE_USER_PCA_ISR_CODE1_END>>
}

程序中我们定义了一个 u16 类型的全局变量 CH0_CAPTURE_STA, 此变量可以看成类似一个 16 位的寄存器, bit15 用来表示捕获完成, bit14 用来表示捕获到低电平, bit13-0 用来表示捕获低电平后定时器溢出次数。 程序中还定义了一个u16 类型的全局变量 CH0_CAPTURE_VAL, 用来记录捕获到下降沿时 PCA0 计数值。这两个全部变量的申明在 pca.h 文件中, 在 pca.c 文件处有它们的定义。

要计算输入信号的低电平脉宽, 根据输入捕获的工作原理, 需要先捕获一次下降沿, 然后再捕获一次上升沿, 在低电平期间还需要对 PCA 定时器溢出进行判断, 统计定时器溢出次数。 由于输入捕获初始化函数中就已经设置为下降沿捕获,并且 CH0_CAPTURE_STA 变量初始值为 0, 所以当捕获到第一个下降沿时, 将CH0_CAPTURE_STA、CH0_CAPTURE_VAL 和 PCA 计数器清 0, 然后将 CH0_CAPTURE_STA的 bit14 置 1, 表示已经捕获到低电平, 此时还需要将输入捕获极性设置为上升沿捕获, 等待上升沿到来。 如果等待上升沿期间, 计数器出现溢出, 就在CH0_CAPTURE_STA 内累计溢出次数, 如果 CH0_CAPTURE_STA 的 bit13-0 都累计满,我们就强制标记捕获完成(CH0_CAPTURE_STA 的 bit16 置 1, 虽然此时还没有捕获到上升沿) , 当上升沿到来的时, 首先将 CH0_CAPTURE_STA 的 bit15 置 1, 表示成功捕获一次低电平, 然后读取 PCA0 计数器内值保存到 CH0_CAPTURE_VAL 内,最后设置捕获极性为下降沿, 回到初始捕获状态。

这样我们就完成了一次低电平的捕获, 只要 CH0_CAPTURE_STA 的 bit15 一直为 1, 就不会进行第二次捕获, 这个时候如果主函数把捕获到低电平数据处理后,将 CH0_CAPTURE_STA 的 bit15 清零就可以进入第二次捕获了。

20.3.2.3 main.c 文件

cpp 复制代码
//<<AICUBE_USER_HEADER_REMARK_BEGIN>>
/* 深圳市普中科技有限公司(PRECHIN 普中)
 * 在线视频:https://space.bilibili.com/2146492485/video
       官网:www.prechin.cn

 * 实验名称:输入捕获实验
 * 
 * 接线说明:参考电路图
 * 
 * 实验现象:程序下载成功后,K1键按下后松开,串口助手输出检测低电平时间
 * 
 * 注意事项:使用一根导线,将P32与P20口连接一起
 * 
 */
//<<AICUBE_USER_HEADER_REMARK_END>>


#include "config.h"                     //默认已包含stdio.h、intrins.h、ai_usb.h等头文件

////////////////////////////////////////
// 项目主函数
// 入口参数: 无
// 函数返回: 无
////////////////////////////////////////
void main(void)
{
    //<<AICUBE_USER_MAIN_INITIAL_BEGIN>>
    // 在此添加用户主函数初始化代码
    u32 indata=0;
    //<<AICUBE_USER_MAIN_INITIAL_END>>

    SYS_Init();

    printf("Hello World !\n");

    //<<AICUBE_USER_MAIN_CODE_BEGIN>>
    // 在此添加主函数中运行一次的用户代码
    //<<AICUBE_USER_MAIN_CODE_END>>

    while (1)
    {
        //<<AICUBE_USER_MAIN_LOOP_BEGIN>>
        // 在此添加主函数中用户主循环代码
        if(CH0_CAPTURE_STA&0x8000) //成功捕获
		{
			indata=CH0_CAPTURE_STA&0x3fff;
			indata*=0xffff; //溢出次数乘以一次的计数次数时间*0.1us
			indata+=CH0_CAPTURE_VAL;//加上低电平捕获的时间
			printf("低电平持续时间:%.1f us\r\n",(float)indata/10); 
			CH0_CAPTURE_STA=0; //开始下一次捕获
		}
        //<<AICUBE_USER_MAIN_LOOP_END>>
    }
}

主函数实现功能主要初始化系统时钟及相应外设端口, while 循环内就不断检测 CH0_CAPTURE_STA 的 bit15 标志是否为 1, 即是否成功捕获到低电平。 如果为 1 表示成功捕获, 然后读取 CH0_CAPTURE_STA 变量内 bit13-0 溢出次数, 每一次溢出时间是0xffff*0.1us, 最后还要加上CH0_CAPTURE_VAL的值保存在indata内, 通过 printf 函数打印低电平时间, 在输出函数内将 indata/10 是将前面的0.1us 换算为 us 单位, 然后将 CH0_CAPTURE_STA 变量清 0 即可, 等待下次捕获。

20.4 实验现象

将程序编译下载到目标板运行, 打开串口助手"\5--开发工具\5-串口调试助手\串口调试助手(丁丁) \sscom5.13.1.exe" , 实验现象: 使用一根导线,将 P20 管脚与 P32 管脚连接, 按下 K1 键后松开可在串口助手上输出捕获到低电平的时间。

相关推荐
d111111111d1 小时前
直流电机位置式 PID 控制 和 舵机的区别
笔记·stm32·单片机·嵌入式硬件·学习
d111111111d4 小时前
了解Modbus
网络·笔记·stm32·单片机·嵌入式硬件·学习
三佛科技-134163842124 小时前
主控FT32F031便携式吸尘器方案,迷你手持吸尘器MCU控制方案开发
单片机·嵌入式硬件·物联网·智能家居·pcb工艺
一个平凡而乐于分享的小比特5 小时前
一文读懂MCU与FPGA:核心区别、协同之道与双修秘籍
单片机·fpga开发·职场发展·mcu开发
踏着七彩祥云的小丑6 小时前
嵌入式——认识电子元器件——微动开关系列
单片机·嵌入式硬件
调光IC-小雅6 小时前
解析FP62××系列限流保护机制:为何它是DC/DC芯片的安全底线
单片机·嵌入式硬件
天天爱吃肉82186 小时前
场地整车在环仿真测试系统及总线注入研究|新能源智驾研发硬核干货
大数据·人工智能·功能测试·嵌入式硬件·汽车
gihigo19986 小时前
MAX30102 + STM32 人体血氧饱和度(SpO₂)测量方案
stm32·单片机·嵌入式硬件
LCG元7 小时前
STM32实战:基于uC/OS-III的STM32移植与多任务应用
stm32·单片机·嵌入式硬件