串口的使用 1、为什么要用串口?
自上一篇写的时间是1月20号,今6月7号了,半年没更新了。
这半年发生了什么?过完年就去找公司实习,在那里自我感觉进步很大。其实在公司大多都是自学,师傅基本不会给你说什么。但这并不能说明你的师傅对你不好,带我的那个师傅只比我高一届,但他的水平比我高的好多届。他也是自学,也没人告诉他该怎么做,因为老板也不太懂。所以自学能力很重要,当然有人带你的话,这样会更好。
不说这些了,串口在调试的时候作用非常大。也学我们在学51的时候,只是将程序下载到开发板,看看是否能运行起来,通过数码管将结果显示出来,从而就知道程序设计的正确性。以前我也是这样做的,没什么不好。
在公司实习的时候,他们调试都是使用串口打印输出信息,观察程序从上电、初始化、运行数据什么的全部都显示到PC机上。然后再一句一句分析它的打印信息,从而找到出错的源头。这使我对串口的认识有更深了一步,所以我决定在学习STM32的时候,开发流程跟在公司学的方法一样——使用串口,观察打印信息。
2、STM32跟PC机(也就是电脑)如何连接
我的STM32F103C8T6只是裸板,没有串口芯片,当然用的也是学生机——笔记本电脑,同样也没串口。
解决办法1、买一块 MAX3232转接板+一条USB转串口线 +邮费=30块左右
2、只需要买一块PL2303的USB转接板。这样就将第一种的转接板和连接结合到一起了。
不过我用的是第一种,MAX3232+USB的串口线,为什么不用方便的2种?
max3232对于没有串口的开发板可以充当电平转换芯片,如何开发板有了电平转换芯片,我便使用USB转串口线经行连接,这样便灵活了。第二种只是用在既没转换芯片也没USB转串口的情况,不过对于最小系统板来说,它既可以下载程序,又可以当做串口来调试。至于台式机就不需要USB转串口线了,普通串口线即可。
连接示意如下所示:
3、代码分析
再写这里之前,应该已经学过模块化编程了,STM32的每个XXX.c 和xxx.h 这都是模块化编程。良好的程序,与其好的代码风格有关。你的代码风格跟你接触教你写代码的有很大关系。以前刚刚学习单片机编程,我还不信,现在我承认,跟教我单片机的老师风格有些像。
这里我做的是一个串口发送数据到PC机的例子:
要让STM32能够顺利发出数据,要进行如下配置
PA9,PA10管脚要配置,USART也需要配置波特率,数据有几位,停止位,数据流等。
USART和uart有什么区别USART在做串口时,两者并不区别,但是USART有SPI的功能。还有串口通信为什么要配置波特率,停止位,硬件数据留这些,以前我也没想过,现在只觉得协议这个东西,是一个好的标准。
建立一个usart_debug.c的文本,内容如下
#include"usart_debug.h"
void GPIO_Configuration(void)
{
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能UASRT的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA的时钟,开始的时候,我没用这句话,调了两天,跟源码一句一句比才知道
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz; //波特率较高,IO翻转需较高频率
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出;我看网上有人说设置成GPIO_Mode_Out_PP普通推挽输出也行,但实践出真知,我试了发送是乱码。;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //配置成浮空输入,既然是输入所以就不用配置IO口的频率了
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
void USART1_config(void)
{
USART_InitTypeDefUSART_InitStructure;
USART_InitStructure.USART_BaudRate= 115200;//配置波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //配置数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位
USART_InitStructure.USART_Parity= USART_Parity_No ;//奇偶校验位
USART_InitStructure.USART_HardwareFlowControl= USART_HardwareFlowControl_None; //硬件流
USART_InitStructure.USART_Mode =USART_Mode_Rx |USART_Mode_Tx;
USART_Init(USART1, &USART_InitStructure);
USART_Cmd(USART1, ENABLE);
}
//这段很重要,如果要使用printf函数打印信息,需要加fputc函数,就需要对printf函数重定向到串口,以前工作中他们老是提重定向,什么串口重定向,USB重定向什么的,我也是云里雾里,如今给我的感觉就是将上层函数实现对底层硬件的操作
intfputc(int ch,FILE*f){
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) !=SET); //网上的一些函数里面是没有这一句代码,如果不加的话,打印时第一个字符就会没有,原因据说是硬件复位后,USART_FLAG_TC被置一了,而要发送数据必须让其为底才可以,一表示数据发送发出的标志,也可以用这样一句USART_ClearFlag(USART2,USART_FLAG_TC);清楚标准位。可是我没这样做一样发成功了,这个疑惑以后再想明白。
USART_SendData(USART1, (uint16_t)ch);
while(USART_GetFlagStatus(USART1, USART_FLAG_TC) !=SET);
return ch;
}
void usart_debug_config(void)//提供给main函数调用的串口配置函数
{
GPIO_Configuration(); //IO口配置
USART1_config();//串口配置
}
还就是usart_debug.h
#ifndef __usart_debug_H
#define__usart_debug_H
#include "stm32f10x.h"
#include
void usart_debug_config(void);
int fputc(int ch, FILE *f);
#endif// __USART1_H
main函数:
这里使用两种方式一种是 使用普通的方式发送,另一种使用printf函数
其实还有一种USART_printf函数来实现,这里不做介绍。有空看看区别一下printf和usart_printf,据说是支持格式多少的问题
#include"stm32f10x.h"
#include"usart_debug.h" //包含main函数里的调用函数
int main(void)
{
unsigned char TxBuf1[100] ={"发送字符串!!!rn"};
inti;
SystemInit();
usart_debug_config();
for( i = 0; TxBuf1[i] != '