|   一派掌門 二十級 | 
              #include <stdio.h>#include <string.h>
 #include <stm32f10x.h>
 
 #define BIT(reg, bit) (((reg) & (bit)) != 0)
 
 struct fifo
 {
 uint8_t buf[127];
 uint8_t front;
 uint8_t rear;
 } usartbuf;
 
 void fifo_init(struct fifo *f)
 {
 f->front = f->rear = 0;
 }
 
 uint8_t fifo_full(struct fifo *f)
 {
 return f->front == (f->rear + 1) % sizeof(f->buf);
 }
 
 uint8_t fifo_empty(struct fifo *f)
 {
 return f->front == f->rear;
 }
 
 uint8_t fifo_in(struct fifo *f, uint8_t data)
 {
 if (fifo_full(f))
 return 0;
 f->buf[f->rear] = data;
 f->rear = (f->rear + 1) % sizeof(f->buf);
 return 1;
 }
 
 uint8_t fifo_out(struct fifo *f, uint8_t *data)
 {
 if (fifo_empty(f))
 return 0;
 *data = f->buf[f->front];
 f->front = (f->front + 1) % sizeof(f->buf);
 return 1;
 }
 
 int fputc(int ch, FILE *fp)
 {
 if (fp == &__stdout)
 {
 if (ch == '\n')
 {
 USART1->DR = '\r';
 while ((USART1->SR & USART_SR_TXE) == 0);
 }
 USART1->DR = ch;
 while ((USART1->SR & USART_SR_TXE) == 0);
 }
 return ch;
 }
 
 int fgetc(FILE *fp)
 {
 uint8_t value;
 if (fp == &__stdin)
 {
 while (!fifo_out(&usartbuf, &value));
 return value;
 }
 return 0;
 }
 
 int main(void)
 {
 char str[21];
 uint32_t value;
 RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
 PWR->CR = PWR_CR_DBP;
 
 RCC->BDCR = RCC_BDCR_BDRST; // Backup Domain必须要复位后才能重设RTC时钟
 
 // HSE/128: 外部大晶振128分频
 //RCC->BDCR = RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL;
 
 // LSE: 外部小晶振
 //RCC->BDCR = RCC_BDCR_LSEON;
 //while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0);
 //RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_0;
 
 // LSI: 内部小晶振
 RCC->CSR = RCC_CSR_LSION;
 while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
 RCC->BDCR = RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_1;
 
 fifo_init(&usartbuf);
 RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN;
 GPIOA->CRH = 0x4b0;
 USART1->BRR = 0x271;
 USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;
 NVIC_EnableIRQ(USART1_IRQn);
 printf("PWR->CR=0x%x, RCC->BDCR=0x%x, RCC->CSR=0x%x\n", PWR->CR, RCC->BDCR, RCC->CSR);
 
 NVIC_EnableIRQ(RTC_IRQn);
 while (1)
 {
 scanf("%20s", str);
 if (strcmp(str, "test") == 0)
 printf("Hello World!\n");
 else if (strcmp(str, "fifopos") == 0)
 printf("pos=%d\n", usartbuf.front);
 else if (strcmp(str, "get") == 0)
 {
 scanf("%20s", str);
 if (strcmp(str, "RTC_CRH") == 0)
 printf("OWIE=%d ALRIE=%d SECIE=%d\n", BIT(RTC->CRH, RTC_CRH_OWIE), BIT(RTC->CRH, RTC_CRH_ALRIE), BIT(RTC->CRH, RTC_CRH_SECIE));
 else if (strcmp(str, "RTC_CRL") == 0)
 printf("RTOFF=%d CNF=%d RSF=%d OWF=%d ALRF=%d SECF=%d\n", BIT(RTC->CRL, RTC_CRL_RTOFF), BIT(RTC->CRL, RTC_CRL_CNF), BIT(RTC->CRL, RTC_CRL_RSF), BIT(RTC->CRL, RTC_CRL_OWF), BIT(RTC->CRL, RTC_CRL_ALRF), BIT(RTC->CRL, RTC_CRL_SECF));
 else if (strcmp(str, "RTC_DIV") == 0)
 printf("%d\n", (RTC->DIVH << 16) | RTC->DIVL);
 else if (strcmp(str, "RTC_CNT") == 0)
 printf("%d\n", (RTC->CNTH << 16) | RTC->CNTL);
 else
 printf("Unknown register: %s!\n", str);
 }
 else if (strcmp(str, "set") == 0)
 {
 scanf("%20s", str);
 while ((RTC->CRL & RTC_CRL_RTOFF) == 0);
 if (strcmp(str, "RTC_CRH") == 0)
 {
 scanf("%x", &value);
 RTC->CRH = value & 7;
 }
 else if (strcmp(str, "RTC_CRL") == 0)
 {
 scanf("%x", &value);
 RTC->CRL = value & 0x1f;
 }
 else if (strcmp(str, "RTC_PRL") == 0)
 {
 scanf("%d", &value);
 RTC->PRLL = value & 0xffff;
 RTC->PRLH = (value >> 16) & 0x0f;
 }
 else if (strcmp(str, "RTC_CNT") == 0)
 {
 scanf("%d", &value);
 RTC->CNTL = value & 0xffff;
 RTC->CNTH = (value >> 16) & 0xffff;
 }
 else if (strcmp(str, "RTC_ALR") == 0)
 {
 scanf("%d", &value);
 RTC->ALRL = value & 0xffff;
 RTC->ALRH = (value >> 16) & 0xffff;
 }
 else
 printf("Unknown register: %s!\n", str);
 }
 else if (str[0] != ';')
 printf("Unknown command: %s!\n", str);
 }
 }
 
 void USART1_IRQHandler(void)
 {
 if (USART1->SR & USART_SR_RXNE)
 fifo_in(&usartbuf, USART1->DR);
 }
 
 void RTC_IRQHandler(void)
 {
 uint8_t data = RTC->CRL;
 RTC->CRL &= ~RTC->CRH;
 printf("Interrupt triggered: RTC_CRL=0x%x\n", data);
 }
 
 |