微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > STM8 TIM1 测试外部信号频率

STM8 TIM1 测试外部信号频率

时间:10-02 整理:3721RD 点击:
亲自测试通过  所用硬件电路 数码管共阴, IO口 PB  PD PC 口
信号输出口PE0  信号采集口PC1 ,  或直接把测试信号 输入PC1 口 ,注意电压  啊,信号电压高的话STM8 不能承受
/* MAIN.C file
*
* Copyright (c) 2002-2005 STMicroelectronics
*/
/****
*   实现功能 利用TIM1 输入捕获功能捕获输入信号的周期占空比
*
* STM8 输入捕获功能TIM1 测量周期的原理 是 当被测量信号的边沿 (下降或上升) 到来时
* 启动定时器开始定时 等被测量信号 边沿在一次到来时 读取定时器 的计数值 从而就可以计算出来
* 第二次测量的计数值 -  第一次测量的计数值 = Y   系统晶振频率/Y = 测量到的信号的频率
*
* 被测量信号的周期  占空比类似
* STM8 捕获有4个端口 TIM1 啊
*  这个输入捕获功能有些复杂 请仔细看 所有的注释  漏掉一点 寄存器的说明就搞不懂了
*  输入捕获模式下,当检测到ICi 信号上相应的边沿后,计数器的当前值被锁存到捕获比较寄存器TIM1_CCRx 中
*  TIM1_CNTRH  TIM1_CNTRL 的值被锁存在 TIM1_CCR1H  TIM1_CCR1L 中
*  当发生捕获事件 时 相应的 捕获中断标志位 CCiLF 标志 被置1
*  //如果TIM1_IER 寄存器 CCiLE 置位  使能了中断,则产生中断事件 中断请求
*  如果发生捕获事件时 CCiLE 已经是高 那么重复捕获标志位 CCIOF TIM1_SR2 被置1
*  TI1 输入的上升沿时捕获计数器的值TIM1_CCR1 寄存器中步骤如下:
* 选择有效的输入端,配置IO 口这点很重要 配置为输入口 比如PC1 也就是TIM1_CH1
* 所以写入TIM1_CCR1 寄存器总的 CC1S = 01,此时通道配置为输入 并且TIM1_CCR1 寄存器为只读
* TIM1_CCMR1  [  [ICIF[3:0]     IC1PSC[1:0]]  CCIS[1:0] ] 这里选择输入捕获模式
* ICIF[3:0]  配置输入捕获1 滤波器有无采样频率
* IC1PSC[1:0]  配置输入捕获1 是否需要预分频  主要是有些信号过快 或频率过高 这里设置的意思是
* 不如上升沿信号 1S 过来 10000 个, 但采集超过或小于 捕获频率 我们就 10个上升沿或 100个上升沿
* 采集计数一次 这样有稳定性和 准确性考虑。
* CC1S[1:0] 捕获比较 1选择
* 定义通道的方向及输入脚的选择 这位特别注意 你立即写 可能会没有效果
* 这位寄存器 最下 注意 :CC1S 仅在通道关闭时TIM1_CCER1 寄存器CC1E = 0 才可以写。
*  最好 TIM1_CCER1 &= 0B11111110 在写这句
*
* *****************************
* 根据输入信号TIi 特点 可通过配置TIM1_CCMRi  寄存器中的 ICiF 来设置相应输入滤波器的滤波时间
*  上面有说明这就不在写了
************************************
* 选择TI1 通道的有效转换边沿,在TIM1_CCER1 寄存器中写入 CC1P = 0 上升沿。
* TIM1_CCER1  8位 高4位 定义输入捕获2   低4位定义输入捕获1
* CC2NP  CC1NP   输入捕获比较1/2 互补输出极性 =0 高电平有效  =1  低电平有效  这里没有用
* CC2NE  CC1NE   输入捕获比较1/2 互补输出使能 =0 关闭  =1 开启  没有用
* CC2P   CC1P  CC1 或 CC2 配置为输入 = 0 捕获发生在TI1F 的高电平 =1 捕获发生在TI1F  低电平 * *                                                                            这里选择 0
* CC2E   CC1E  输入捕获输出使能位  = 0 禁止捕获 =1 使能捕获
************************************
* 配置预分配  这里希望发生的每个有效电平转换都采集到  这句好好理解  如果8 分频怎么测量到输入的频率
*  8*系统频率/(第二次计数值 -  第一次计数值) = 测量到的频率
****************************************
* 如果需要中断设置 TIM1_IER 寄存器中CC1IE 允许中断  ,这里没有使用中断 下个例子使用
*

*/
#include "stm8s105c4.h"
unsigned long frequency;
unsigned char dutycycle;
unsigned int cvalue1,cvalue2;
unsigned char gewei,shiwei,baiwei,qianwei,dutycycle1,dutycycle2;
unsigned char dis[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//数码管选择共阴极 数码管
void tim1_init(void);  //定时器初始化
void cco_init(void);   //CCO 时钟
void gpio_init(void);  //GPIO 初始化
void display(void);      //显示
void delay(unsigned int t);   //延时





/******************************************************************************/
//配置系统时钟
void CLK_Init(void)
{
/*
  CLK_CKdivR = 0x11;          // 10: fHSI = fHSI RC output/ 4
                              //          = 16MHZ / 4 =4MHZ
                              // 001: fCPU=fMASTER/2. = 2MHZ
*/
        CLK_ECKR |=0X1;   //开启外部时钟
        while(!(CLK_ECKR&0X2)); //等待外部时钟rdy
       
        //外部晶振 = 8MHz
        //CLK_CKdiv = 0XF8   1111 1000  
        //CLK_CKdivR &= 0X00;      //CPU无分频
        //CLK_CKdivR &= 0X07;
        //16000000/128 = 125khz
        //CLK_CKdivR = 0X00;  //不分频
        // 16000000 /8 = 2MHZ
        CLK_CKdivR = 0X00;  // 16分频
        //16000.000/16 = 1MHZ
        CLK_SWR = 0XB4;   //选择外部时钟
        while(!(CLK_SWCR&0X8)); //这里要等
        CLK_SWCR |=0X02;   //使能外部时钟

}

//可配置时钟输出功能 CCO
//用户可以通过配置 CCO 选择外部引脚 输出指定 时钟
//可配置时钟输出寄存器 CLK_CCOR
// CCOBSY  可配置时钟输出忙碌标志位
// CCORDY 可配置时钟输出准备就绪 =0 CCO 时钟可用  =1 CCO时钟不可用
// CCOSEL [3:0] 可配置时钟输出源选择
void cco_init(void)
{
                CLK_CCOR |= 0X03; //Flsi 时钟输出
                //CLK_CCOR |= 0X05; //Fhse 时钟输出
                //CLK_CCOR |= 0X09; //Fcpu 时钟输出
                //CLK_CCOR |= 0X15; //Fcpu/64 时钟输出
               
}

void delay(unsigned int t)
{
               
                while(t--);
}
void gpio_init(void)
{
                PB_ODR = 0XFF;
                PB_DDR = 0XFF;
                PB_CR1 = 0XFF;
                PB_CR2 = 0XFF;
                // PB 口 为 位选
                PD_ODR = 0XFF;
                PD_DDR = 0XFF;
                PD_CR1 = 0XFF;
                PD_CR2 = 0XFF;
                //PB 口 为 段选
               
               
                PE_DDR = 0X01;
                PE_CR1 = 0X01;
                PE_CR2 = 0X01;
               
                PC_DDR &= 0B11111101;   //配置捕获输入 IO 口
          PC_CR1 |= 0B00000010;    //PC1
               
}

void display(void)
{
                qianwei = frequency/1000;
                baiwei = (frequency%1000)/100;
                shiwei = (frequency%100)/10;
                gewei  =   frequency%10;
               
               
                PD_ODR = dis[gewei];
    PB_ODR = 0xfe; //0b11111110;  
                delay(10);
               
                PD_ODR = dis[shiwei]|0x80;  //为什么 与 0X80  显示小数点 用
    PB_ODR = 0xfd; //0b11111101;  //1111 1011
                delay(10);
               
                PD_ODR = dis[baiwei];
    PB_ODR = 0xfb; //0b11111011;  //1111 1101
                delay(50);
               
                PD_ODR = dis[qianwei];
    PB_ODR = 0xf7; //0b111101111;  //1111 1110
                delay(50);
               
               
               
}
void tim1_init(void)
{
                TIM1_CNTRH = 0X00;
                TIM1_CNTRL = 0X00;
                TIM1_PSCRH = 0X00;
                TIM1_PSCRL = 0X00;
               
                TIM1_CCER1 &= (unsigned char ) ~0x01;  
                //TIM1_CCMR1 寄存器 CC1S 写 01 将端口配置为输入 但TIM1_CCMR1 寄存器中有说明
                // CC1S 更改的需要 在通道关闭 TIM1_CCER1 寄存器 CC1E=0 时才可写入
                //首先对 CC1E 位置 0 之后在配置 TIM1_CCMR1;
                TIM1_CCMR1 = 0X01;
//  TIM1_CCMR1 中 CC1S 位=1通道配置为 输入IC1 影射到TI1FP1 上。
//无滤波功能 无预分频
//
    TIM1_CCER1 &= (unsigned char)~0X02;
                //TIM1_CCMR1 |= 0X0C;
    //128KHZ/8=4000
               
                TIM1_CCER1 |= 0X01;
                //捕获使能
                TIM1_CR1 |=0X01;
   //使能定时器计数器
}

void main()
{
unsigned int i;
CLK_CKdivR = 0X00;   //系统时钟不分频
gpio_init();
cco_init();
tim1_init();
CLK_Init();
        while (1)
        {
       
                        //TIM1_CCER1  |= 0X01;
                        //IC1PSC[1:0] 输入捕获1预分频
                        //定义预分频系数 =00 无预分频 捕获输入口上检测
                        //CC1 通道被配置为输入 IC1 影射到 TI1FP1 上
                        //TIM1_CCER1 = 0X00;
                        //
                        while(!(TIM1_SR1 & 0X02));
                        //等待 当通道配置 CC1 配置为输入时该位由硬件置1 有软件清0 通过读TIM1_CCR1L 清0
                        // = 1 计数器值已捕获至 TI1M_CCR1  在IC1 上检测到与所选极性相同的的边沿
                        cvalue1 = (unsigned int )TIM1_CCR1H<<8;
                        cvalue1 |= TIM1_CCR1L;
    TIM1_SR1 &=0xfd;//0B11111101;
               
                //等待第二次置位
    while(!(TIM1_SR1 & 0X02));
//  等待
    cvalue2 = (unsigned int )TIM1_CCR1H<<8;
                cvalue2 |= TIM1_CCR1L;
    TIM1_SR1 &=0xfd;//0B11111101;
               
                //TIM1_CCER1 &= 0Xfe;
                //上面这句注释掉  否则只能看到一次 数码管达到的频率显示
               
               
                frequency = 16000000UL/(cvalue2-cvalue1);
                //frequency =cvalue1;
                frequency = frequency/100;   //这里与显示 小数点 有关系  1000/100 = 10.0  想想是不是啊
                                                                                                                                //不在说明了
                //for(i=0;i<30;i++)
                display();
        }
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top