大家好,欢迎来到IT知识分享网。
需求
一、串口调试的意义
二、串口调试实现流程
1.开时钟
由上图可知,控制USART1和GPIOA的时钟是由APB2外设时钟使能寄存器的第14位和第2位控制的。该模块均为1使能0关闭。
在代码中为:
//开时钟:GPIOA,USART1 RCC->APB2ENR |= 0x01<<2;//GPIOA RCC->APB2ENR |= 0x01<<14;//USART1
2.配置对应的IO口
//配置对应的IO口 GPIOA->CRH &= ~(0x0f<<4);//PA9清0 GPIOA->CRH |= 0x0B<<4;//设置成复用推挽输出 GPIOA->CRH &= ~(0x0f<<8);//PA10清0 GPIOA->CRH |= 0x04<<8;//设置成浮空
3.配置串口1
USART1->CR1 &= ~(0x01<<12);//数据位置0 USART1->CR1 &= ~(0x01<<10);//设置0位校验位 USART1->CR2 &= ~(0x03<<12);//设置1个停止位
//配置串口1 8数据位,0校验位,1停止位,波特率 USART1->CR1 &= ~(0x01<<12);//数据位置0 USART1->CR1 &= ~(0x01<<10);//设置0位校验位 USART1->CR2 &= ~(0x03<<12);//设置1个停止位 USART1->BRR = (39<<4)+1;//设置波特率 USART1->CR1 |= 0x01<<3;//发送使能 USART1->CR1 |= 0x01<<13;//使能串口1
USART1->DR = 'A';
4.printf函数的重定向
int fputc(int ch, FILE *f) {
//printf函数最终会跳转到这里来运行 while((USART1->SR&0x1<<6)==0); //发送数据 USART1->DR = (uint8_t)ch; return ch; }
三、需求的实现
#include "stm32f10x.h" #include "led.h" #include "key.h" #include "delay.h" #include "usart.h" #include "stdio.h" int a,b,c,d;//LED灯的标志位 int main() {
Led_Init(); key_Init(); Beep_Init(); Usart1_Config(); while(1) {
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1)//key1 {
Delay_nms(10); if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1) {
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)==1) {
} Led_Toggle(1); a++; if(a==2) {
printf("LED1灯灭\r\n"); a=0; } else {
printf("LED1灯亮\r\n"); } } } if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_4)==0)//key2 {
Delay_nms(10); if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_4)==0) {
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_4)==0) {
} Led_Toggle(2); b++; if(b==2) {
printf("LED2灯灭\r\n"); b=0; } else {
printf("LED2灯亮\r\n"); } } } if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==0)//key3 {
Delay_nms(10); if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==0) {
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==0) {
} Led_Toggle(3); c++; if(c==2) {
printf("LED3灯灭\r\n"); c=0; } else {
printf("LED3灯亮\r\n"); } } } if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6)==0)//key4 {
Delay_nms(10); if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6)==0) {
while(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6)==0) {
} Led_Toggle(4); d++; if(d==2) {
printf("LED4灯灭\r\n"); d=0; } else {
printf("LED4灯亮\r\n"); } } } } }
usart.c
#include "usart.h" #include "stdio.h" void Usart1_Config() {
//开时钟:GPIOA,USART1 RCC->APB2ENR |= 0x01<<2;//GPIOA RCC->APB2ENR |= 0x01<<14;//USART1 //配置对应的IO口 PA9(tx):复用推挽 PA10(RX):浮空输入 GPIOA->CRH &= ~(0x0f<<4);//PA9清0 GPIOA->CRH |= 0x0B<<4;//设置成复用推挽输出 GPIOA->CRH &= ~(0x0f<<8);//PA10清0 GPIOA->CRH |= 0x04<<8;//设置成浮空 //配置串口1 8数据位,0校验位,1停止位,波特率 USART1->CR1 &= ~(0x01<<12);//数据位置0 USART1->CR1 &= ~(0x01<<10);//设置0位校验位 USART1->CR2 &= ~(0x03<<12);//设置1个停止位 /* 72M/usartdiv/16= usartdiv = 72M/16/ = 39.0625 39.0625 = DIV_Mantissa + (DIV_Fraction/16) DIV_Mantissa(整数部分) = 39 DIV_Fraction(小数部分) = 0.0625*16 = 1; 0000 0010 0111 0001 */ USART1->BRR = (39<<4)+1;//设置波特率 USART1->CR1 |= 0x01<<3;//使能串口发送 USART1->CR1 |= 0x01<<13;//使能串口1 } void SendData(uint8_t data) {
while((USART1->SR&0x01<<6)==0){
}//等待上次发送完成 USART1->DR = data;//发送数据 } int fputc(int ch, FILE *f) {
//printf函数最终会跳转到这里来运行 while((USART1->SR&0x1<<6)==0); //发送数据 USART1->DR = (uint8_t)ch; return ch; }
usart.h
#ifndef _USART_H_ #define _USART_H_ #include "stm32f10x.h" #include "stdio.h" void Usart1_Config(); void SendData(uint8_t data); int fputc(int ch, FILE *f); #endif
key.c
#include "stm32f10x.h" void key_Init() {
//开时钟 RCC->APB2ENR |= 0x01<<4;//PC RCC->APB2ENR |= 0x01<<2;//PA //配置模式 GPIOC->CRL &=~(0X0F << 24);//PC6 key4 GPIOC->CRL |= 0X04 << 24; GPIOC->CRL &=~(0X0F << 20);//PC5 key3 GPIOC->CRL |= 0X04 << 20; GPIOC->CRL &=~(0X0F << 16);//PC4 key2 GPIOC->CRL |= 0X04 << 16; GPIOA->CRL &=~0X0F;//PA0 key1 GPIOA->CRL |= 0X04; } int Get_Key_Val(void) {
int key_val = 0; if(!!(GPIOA->IDR &(0X01 << 0))==1) key_val = 1; if(!!(GPIOC->IDR &(0X01 << 4))==0) key_val = 2; if(!!(GPIOC->IDR &(0X01 << 5))==0) key_val = 3; if(!!(GPIOC->IDR &(0X01 << 6))==0) key_val = 4; return key_val; }
key.h
#ifndef _KEY_H_ #define _KEY_H_ void key_Init(); int Get_Key_Val(void); #endif
led.c
#include "stm32f10x.h" void Led_Init() {
//配置好模式,然后全灭 //开APB2时钟 RCC->APB2ENR |= 0X01 << 6; //配置PE2--PE5为通用推挽输出 GPIOE->CRL &=~(0X0F << 20);//PE5 GPIOE->CRL |= 0X03 << 20; GPIOE->CRL &=~(0X0F << 16);//PE4 GPIOE->CRL |= 0X03 << 16; GPIOE->CRL &=~(0X0F << 12);//PE3 GPIOE->CRL |= 0X03 << 12; GPIOE->CRL &=~(0X0F << 8);//PE2 GPIOE->CRL |= 0X03 << 8; //4个引脚均输出高电平 GPIOE->ODR |= (0x0F << 2); } //开关灯 void Led1_Ctrl(int flag) {
if(!!flag) {
GPIOE->ODR &= ~(0x0F << 2); } else {
GPIOE->ODR |= (0x0F << 2); } } void Led_Toggle(int flag) {
GPIOE->ODR ^= 0x01<<(flag+1); }
led.h
#ifndef _LED_H_ #define _LED_H_ void Led_Init(); void Led1_Ctrl(int flag); void Led_Toggle(int flag); #endif
delay.c
#include "stm32f10x.h" #include "delay.h" void Delay_nus(uint32_t time) {
uint32_t i=0; for(i=0;i<time;i++){
delay1us(); } } void Delay_nms(uint32_t time) {
uint32_t i=0; for(i=0;i<time;i++){
Delay_nus(1000);//延时1ms } }
delay.h
#ifndef _DELAY_H_ #define _DELAY_H_ #include "stm32f10x.h" #define delay1us() {
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();\ __NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();} void Delay_nus(uint32_t time); void Delay_nms(uint32_t time); #endif
总结
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/115003.html