小言_互联网的博客

STM32F103调试串口(USART)模块开发(内含Printf重定向函数说明及模块代码资源)

311人阅读  评论(0)


《《《《《正文》》》》》


 

《前言》

基于UART的串口在实际项目中的应用相当广泛,包括wifi、can、lin等均可使用uart进行通信,方便且成本低;而uart串口功能不仅仅体现在产品使用功能上,在开发调试阶段更是一个必不可少的调试助手。今天就来构建一个基于uart的调试串口功能模块;

 

开发需求:使用stm32f103的usart模块开发一个具有发送任意字符串的调试串口功能的模块;

 

相关代码获取地址:

https://pan.baidu.com/s/1zyrOF18WxIq0H3_4qU7Evg

关注公众号,发送1234,获取提取码;


 

《硬件设计》

TX PA9
RX PA10


 

《加载USART库文件》


 

 

《软件设计》

第一步:中断等级配置函数

void NvicConfig(void){  NVIC_InitTypeDef NVIC_InitStruct;  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;           //USART中断通道  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;   //设置抢占优先级为0  NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;          //设置子优先级为1  NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;             //使能外USART中断通道  NVIC_Init(&NVIC_InitStruct);                           //中断优先级初始化函数}

 

第二步:串口初始化函数

//传入参数为波特率void USART_init(uint32_t baudrate){  GPIO_InitTypeDef GPIO_InitStruct;   //定义GPIO结构体变量  USART_InitTypeDef USART_InitStruct;   //定义串口结构体变量  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);   //使能GPIOA、USART1的时钟  GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;   //配置TX引脚  GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;   //配置PA9为复用推挽输出  GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;   //配置PA9速率  GPIO_Init(GPIOA,&GPIO_InitStruct);   //GPIO初始化函数  GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;   //配置RX引脚  GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;   //配置PA10为浮空输入  GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;   //配置PA10速率  GPIO_Init(GPIOA,&GPIO_InitStruct);   //GPIO初始化函数  USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;   //发送接收模式  USART_InitStruct.USART_Parity=USART_Parity_No;   //无奇偶校验  USART_InitStruct.USART_BaudRate=baudrate;   //波特率  USART_InitStruct.USART_StopBits=USART_StopBits_1;   //停止位1位  USART_InitStruct.USART_WordLength=USART_WordLength_8b;   //字长8位  USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None;   //无硬件数据流控制  USART_Init(USART1,&USART_InitStruct);   //串口初始化函数  USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);    //串口接收中断  USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);    //串口空闲中断  USART_Cmd(USART1,ENABLE);   //使能USART1}

 

第三步:中断处理函数

void USART1_IRQHandler(void){    uint8_t clear = clear; //定义这个变量是针对编译出现“没有用到这个变量”的警告提示    uint8_t res;    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断      {             res = USART1->DR;            //在此做数据接收处理    }    else if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //空闲中断    {      clear = USART1->SR; //读SR寄存器      clear = USART1->DR; //读DR寄存器(先读SR,再度DR,就是为了清除IDIE中断)    }    USART_ClearITPendingBit(USART1,USART_IT_RXNE);}

 

第四步:写发送数据函数

void usart_send(uint8_t *data,uint8_t len){  uint8_t i;  for(i=0;i<len;i++)  {    USART_SendData(USART1,*(data+i));    while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET);  }}

 

第五步:来个简单的测试,主函数:

int main(void){      uint8_t usartSendbuf[5] = {1,2,3,4,5};      NvicConfig();      USART_init(115200);      for(;;)      {        usart_send(usartSendbuf,5);      }}

 

结果:


 

《printf函数重定向》

重定向函数:

int fputc(int ch,FILE *f)   //printf重定向函数{  USART_SendData(USART1,(uint8_t)ch);   //发送一字节数据  while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);   //等待发送完成  return ch;}

我们这里直接写是不行,因为这是C库自带的东西,但是可以重定向到这个函数(printf()在c标准库函数实质是一个宏,实际是调用fputc()函数),fputc()函数默认是把字符输出到调试器控制窗口,所以要想把数据通过USART输出到串口助手,需对基于fputc()的printf()系列函数的输出重定向到USART端口上去。

这里特别注意:打开“Options for target...”->“target”勾选“Use MiclroLIB” 不然用printf会有问题;


 

最后上测试函数:

int main(void){      NvicConfig();      USART_init(115200);      for(;;)      {        printf("System Init Finish\n");        printf("我正在测试\n");      }}

结果:


 

 

《《《《《END》》》》》


转载:https://blog.csdn.net/qq_22520215/article/details/115802140
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场