#include <stm32f10x.h>
#define _BV(n) (1 << (n))
uint8_t num[2] = {0, 0}; // 數碼管兩側顯示的數字 const uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; uint8_t buf[8]; // 存放所接收內容的數組
void delay(void) { uint16_t i; for (i = 0; i < 20000; i++); }
void ser_in(uint8_t data) { uint8_t i; for (i = 0; i < 8; i++) { GPIOB->BRR = GPIO_BRR_BR9; // SCLK=>PB9 if (data & 0x80) GPIOB->BSRR = GPIO_BSRR_BS7; // DIO=>PB7 else GPIOB->BRR = GPIO_BRR_BR7; data <<= 1; GPIOB->BSRR = GPIO_BSRR_BS9; } }
void par_out(void) { GPIOB->BRR = GPIO_BRR_BR8; // RCLK=>PB8 GPIOB->BSRR = GPIO_BSRR_BS8; }
void seg_scan(void) { uint8_t i; uint8_t n = num[0]; for (i = 0; i <= 2; i++) { ser_in(seg8[n % 10]); ser_in(_BV(i)); par_out(); delay(); n /= 10; } n = num[1]; for (i = 5; i <= 7; i++) { ser_in(seg8[n % 10]); ser_in(_BV(i)); par_out(); delay(); n /= 10; } }
int main(void) { // 配置數碼管輸出端口 RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; GPIOB->CRL = 0x30000000; // PB7~9設為輸出 GPIOB->CRH = 0x00000033; // 配置串口 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN; GPIOA->CRH = 0x000008b0; // PA9(TX)設為復用50MHz推輓輸出, PA10(RX)設為輸入 GPIOA->BSRR = GPIO_BSRR_BS10; // PA10帶上拉輸入 USART1->BRR = 0x1d4c; // 波特率9600 USART1->CR1 |= USART_CR1_UE | USART_CR1_RE | USART_CR1_TE; // 打開串口, 允許發送和接收 USART1->CR3 |= USART_CR3_DMAR; // 配置DMA // USART1接收通道是DMA1的通道5, 這個不可更改! RCC->AHBENR |= RCC_AHBENR_DMA1EN; // 開DMA1時鐘 DMA1_Channel5->CNDTR = sizeof(buf); // 傳輸的數據量為buf數組的容量 DMA1_Channel5->CPAR = (uint32_t)&USART1->DR; // 源地址為串口的DR寄存器 DMA1_Channel5->CMAR = (uint32_t)buf; // 目的地址為buf數組 DMA1_Channel5->CCR |= DMA_CCR5_EN | DMA_CCR5_TCIE | DMA_CCR5_CIRC | DMA_CCR5_MINC; // 打開DMA通道及其中斷, 開循環模式, 目的地址buf自動增加 NVIC->ISER[DMA1_Channel5_IRQn / 32] |= _BV(DMA1_Channel5_IRQn % 32); while (1) seg_scan(); }
// DMA傳輸完畢中斷 void DMA1_Channel5_IRQHandler(void) { DMA1->IFCR |= DMA_IFCR_CTCIF5; num[0] = buf[num[1] % 8]; // 根據次數除以8的餘數確定數碼管右側顯示哪個數據 num[1]++; // 中斷次數 }
|