#include <stm32f10x.h>
#define _BV(n) (1 << (n))
uint8_t cnt = 0; // 匹配計數 uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
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); else GPIOA->BRR = _BV(0); GPIOC->BSRR = _BV(15); data <<= 1; } }
void ParOut(void) { GPIOC->BRR = _BV(14); GPIOC->BSRR = _BV(14); }
void seg_scan(uint8_t i) { while (i--) { // 數碼管最高位顯示比較匹配次數 SerIn(seg8[cnt % 10]); SerIn(_BV(7)); ParOut(); delay(); // 數碼管只顯示前兩位變得慢的數值 SerIn(seg8[TIM1->CNT % 10000 / 1000]); SerIn(_BV(1)); ParOut(); delay(); SerIn(seg8[TIM1->CNT % 1000 / 100]); SerIn(_BV(0)); ParOut(); delay(); } }
int main(void) { RCC->APB2ENR = _BV(2) | _BV(4) | _BV(11); // 開啟PA、PC和TIM1時鐘, 不需要開啟AFIO的時鐘 GPIOA->CRH = 0x0000000b; // PA8設為復用50MHz推輓輸出 GPIOA->CRL = 0x00000003; // PA0設為50MHz推輓輸出 GPIOC->CRH = 0x33000000; // PC14~15設為50MHz推輓輸出
TIM1->ARR = 3099; // 計數值 TIM1->PSC = 65535; // 定時器分頻 TIM1->DIER = _BV(1); // CC1IE=1, 開輸出比較中斷 NVIC->ISER[0] = _BV(27); // 允許執行輸出比較中斷函數 TIM1->CCR1 = 2000; // 比較值 TIM1->CCMR1 = 0x30; // OC1M=011, 匹配時翻轉輸出電平 TIM1->BDTR = _BV(15); // 注意: 一定要打開主輸出(MOE=1), 否則PA8輸出端只能輸出低電平! TIM1->CCER = 0x01; // CC1E=1, 開啟通道1輸出 // 刷新寄存器 TIM1->CR1 = 0x54; // URS=1 TIM1->EGR = 0x01; // UG=1 // 開始計數(向上計數模式) TIM1->CR1 = 0x01; // CEN=1 while (1) { seg_scan(1); } }
// 輸出比較中斷 void TIM1_CC_IRQHandler(void) { TIM1->SR &= ~_BV(1); // CC1IF=0 //TIM1->CR1 &= ~_BV(0); // CEN=0, 關定時器 cnt++; if (cnt > 9) cnt = 0; }
|