#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; }
|