| 
            
            
             
              #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]++; // 中断次数 }              
                       |