| 
              #include <stm32f10x.h>
 uint8_t seg8[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e};
 uint16_t num = 0;
 
 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;
 uint16_t numbuf = num;
 for (i = 0; i <= 4; i++)
 {
 ser_in(seg8[numbuf % 10]);
 ser_in(1 << i);
 par_out();
 delay();
 numbuf /= 10;
 }
 }
 
 int main(void)
 {
 uint8_t i;
 RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
 PWR->CR |= PWR_CR_DBP; // 允许写入后备寄存器
 
 // 上电复位: PORRSTF=PINRSTF=1
 // 复位键复位: PINRSTF=1
 if (RCC->CSR & RCC_CSR_PORRSTF)
 num = 1970; // 通电时写入初值
 else
 num = BKP->DR1; // 复位时读取寄存器值
 if (RCC->CSR & RCC_CSR_PINRSTF)
 BKP->DR1 = num + 1; // 每次复位都把寄存器的值加1
 if (RCC->CSR & RCC_CSR_IWDGRSTF)
 BKP->DR1 = num - 1; // 如果是看门狗复位则减去1
 RCC->CSR |= RCC_CSR_RMVF; // 清除复位标志信息
 
 /* 配置GPIO口*/
 RCC->APB2ENR = RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN;
 GPIOB->CRL = 0x30000000;
 GPIOB->CRH = 0x00000033;
 GPIOC->CRL = 0x00000080; // PC1设为带电阻输入
 GPIOC->BSRR = GPIO_BSRR_BS1; // PC1带上拉电阻输入
 
 IWDG->KR = 0x5555; // 开始配置
 IWDG->PR = 3; // 32分频, f=40kHz/32=1250Hz->0.8ms
 IWDG->RLR = 1250; // 定时时间: 1250*0.8ms=1s, 1250=0x4e2
 // 写入后不需要等待PVU, RVU标志位清零
 IWDG->KR = 0xcccc; // 启动看门狗
 IWDG->KR = 0xaaaa; // 导入上述配置
 
 while (1)
 {
 for (i = 0; i < 20; i++)
 seg_scan();
 if ((GPIOC->IDR & GPIO_IDR_IDR1) == 0)
 IWDG->KR = 0xaaaa; // 如果PC1键按住不放(低电平), 则喂狗
 }
 }
 
 |