设置 | 登录 | 注册

作者共发了2篇帖子。

【程序】STM32定時器1輸入捕獲

1楼 巨大八爪鱼 2016-12-30 21:19
#include <stm32f10x.h>

#define _BV(n) (1 << (n))

uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
uint8_t data = 0;
uint8_t flag = 0;

void delay(void)
{
    uint32_t i;
    for (i = 0; i < 20000; i++);
}

void SerIn(uint8_t data)
{
    uint8_t i;
    for (i = 0; i < 8; i++)
    {
        GPIOC->BRR = _BV(15);
        if (data & 0x80)
            GPIOA->BSRR = _BV(0); // 之前的PC13信號線轉移到了PA0上,因為使用了上面接的LED
        else
            GPIOA->BRR = _BV(0);
        GPIOC->BSRR = _BV(15);
        data <<= 1;
    }
}

void ParOut(void)
{
    GPIOC->BRR = _BV(14);
    GPIOC->BSRR = _BV(14);
}

int main(void)
{
    RCC->APB2ENR = _BV(2) | _BV(4) | _BV(11); // 開啟PA、PC和TIM1時鐘
    GPIOA->CRH = 0x00000008; // PA8設為輸入
    GPIOA->CRL = 0x00000003;
    GPIOA->BSRR = _BV(8); // PA8為帶上拉的輸入
    GPIOC->CRH = 0x33300000; // PC13~15設為輸出
    GPIOC->BSRR = _BV(13); // 熄滅LED指示燈

    TIM1->ARR = 25500; // 數碼管只顯示前三位變得慢的數值
    TIM1->PSC = 65535;
    TIM1->DIER = 0x03; // UIE=1, CC1IE=1
    NVIC->ISER[0] = _BV(25) | _BV(27);
    
    // 配置輸入比較
    //TIM1->CCMR1 = 0xf1; // CC1S=01, IC1F=1111
    TIM1->CCMR1 = 0x01; // CC1S=01, 只有不進行按鍵消抖才有可能出現overcapture
    TIM1->CCER = 0x03; // CC1P=1, CC1E=1
    
    // 刷新寄存器
    TIM1->CR1 = 0x54; // URS=1
    TIM1->EGR = 0x01; // UG=1
    
    // 開始計數
    TIM1->CR1 = 0x351; // CKD=10, CEN=1
    
    while (1)
    {
        // 顯示計數器的高三位的值
        SerIn(seg8[TIM1->CNT / 10000]);
        SerIn(_BV(2));
        ParOut();
        delay();
        
        SerIn(seg8[TIM1->CNT % 10000 / 1000]);
        SerIn(_BV(1));
        ParOut();
        delay();
        
        SerIn(seg8[TIM1->CNT % 1000 / 100]);
        SerIn(_BV(0));
        ParOut();
        delay();
        
        // 向下計數時顯示負號
        if (TIM1->CR1 & _BV(4))
        {
            SerIn(0xbf);
            SerIn(_BV(3));
            ParOut();
        }
        delay();
        
        // 顯示捕獲的輸入
        SerIn(seg8[data / 100]);
        SerIn(_BV(6));
        ParOut();
        delay();
        
        SerIn(seg8[data % 100 / 10]);
        SerIn(_BV(5));
        ParOut();
        delay();
        
        SerIn(seg8[data % 10]);
        SerIn(_BV(4));
        ParOut();
        delay();
        
        // 顯示是否有overcapture標誌
        if (flag)
        {
            SerIn(0xbf);
            SerIn(_BV(7));
            ParOut();
        }
        delay();
    }
}

// 定時器溢出中斷函數
void TIM1_UP_IRQHandler(void)
{
    TIM1->SR &= ~_BV(0); // Status register (UIF: Update interrupt flag = 0)
    GPIOC->ODR ^= _BV(13); // 定時器溢出中斷觸發後反轉LED指示燈
}

// 輸入捕獲中斷函數
void TIM1_CC_IRQHandler(void)
{
    data = TIM1->CCR1 / 100; // 讀計數器的值, 同時清除CC1IF
    if (TIM1->SR & _BV(9))
    {
        flag = 1;
        TIM1->SR &= ~_BV(9); // CC1OF=0
    }
    else
        flag = 0;
}
2楼 巨大八爪鱼 2016-12-30 21:27

每按下4個按鍵才捕獲一次(對輸入信號進行四分頻),並進行按鍵消抖:
TIM1->CCMR1 = 0xf9; // CC1S=01, IC1PSC=10, IC1F=1111

只要進行了按鍵消抖,那麼就幾乎不可能出現overcapture(信號遺漏)。

内容转换:

回复帖子
内容:
用户名: 您目前是匿名发表。
验证码:
看不清?换一张
©2010-2025 Purasbar Ver3.0 [手机版] [桌面版]
除非另有声明,本站采用知识共享署名-相同方式共享 3.0 Unported许可协议进行许可。