#include <stm32f10x.h>
#include <string.h>
#define _BV(n) (1 << (n))
uint32_t num = 12345678;
const uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
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;
uint32_t n = num;
for (i = 0; i <= 7; i++)
{
ser_in(seg8[n % 10]);
ser_in(_BV(i));
par_out();
delay();
n /= 10;
}
}
int main(void)
{
const char *str = "By choosing one of ST's microcontrollers for your embedded application, you gain from our leading expertise in MCU architecture, technology, multi-source manufacturing and support.\n";
// 配置數碼管輸出端口
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_DMAT; // 允許通過DMA發送數據
// 配置DMA
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // 開DMA1時鐘
DMA1_Channel4->CNDTR = strlen(str); // 數據大小為字符串的長度
DMA1_Channel4->CPAR = (uint32_t)&USART1->DR; // 目的地址為串口的DR寄存器(外設地址)
DMA1_Channel4->CMAR = (uint32_t)str; // 源地址為要發送的字符串(內存地址)
DMA1_Channel4->CCR |= DMA_CCR4_EN | DMA_CCR4_TCIE | DMA_CCR4_MINC | DMA_CCR4_DIR; // 打開DMA通道及其中斷, 內存地址str自動增加, 方向為從內存中讀取
NVIC->ISER[DMA1_Channel4_IRQn / 32] |= _BV(DMA1_Channel4_IRQn % 32);
while (1)
seg_scan();
}
// DMA傳輸完畢中斷
void DMA1_Channel4_IRQHandler(void)
{
DMA1->IFCR |= DMA_IFCR_CTCIF4;
num = 87654321;
}