1.GPIO的初始化
MODE
#include “stm32f10x_gpio.h”
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
2.GPIO读取
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOB, &GPIO_InitStructure);
3.GPIO输出
对所以端口操作的时候可以调用 GPIO_Pin_All
USART
第一步:时钟初始化,包括USART时钟和GPIO时钟
第二步:配置发送接收GPIO,发送端推挽复用输出AFPP;接收端浮空输入或者带上拉输入
IN_FLOATING
第三步:配置USART模块,包括波特率数据位等的配置
第三步:发送数据用USART_SendData();判断发送完毕用USART_GetFlagStatus();返回的TXE(TX empty)和RESET与SET比较。
第四步:接收数据的方式有很多。查询方式,采用USART_GetFlagStatus()查询RXNE(RX not empty)和RESET与SET比较。第二种是中断方式,打开接收寄存器非空中断事件,在中断函数里实现数据的读取,节省CPU资源。开中断函数是USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); 中断读取UASRT方式
void USART1_IRQHandler(void) { }
TXE标志在读标志(USART_GetITStatus)再UASRT_SendData之后清零,RXNE标志在USART_ReceiveData之后清零 1.初始化过程
a) 首先对复用管脚的GPIO初始化 TX的配置为:
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); RX的配置为:
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); b) 配置USART:
USART_InitStructure.USART_BaudRate = 19200;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No ; receive = (u8)USART_ReceiveData(USART1); USART_SendData(USART1,receive);
USART_ClearFlag(USART1,USART_FLAG_RXNE);
//RXNE清零
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, &USART_InitStructure); 注意还要打开USART使能函数: USART_Cmd(USART2,ENABLE); 具体参数意义为:
Stm32f103zbt6管脚如下: USART2 PA2 TX PA3 RX USART1 PA10 RX PA9 TX USART3 PB10 TX PB11 RX
关于通过重定向函数int fputc(int ch,FILE *f);来实现printf函数的串口打印说明:
1.fputc函数和printf在stdio.h中,因为是底层硬件流相关的函数,实现方法不是单单C代码,因此只能找到它们的宏定义,不能通过go to definition找到具体函数体。重定向时注意包含stdio.h头文件。
2.重定向函数编写完以后,一个非常重要的设置是,记得勾选target option界面的Use MicroLIB选项,这里吃亏过,调了一下午都不知道为什么。这个是标准库的辅助库,虽然不是很懂,还有待别人指点,大致意思是,在嵌入式里用不到很多库函数,加载进去浪费资源,因此把库分一块出来,可选可不选,蛋疼的是printf函数就在这个库里面,因为嵌入式开发不会在电脑屏幕里显示东西,所以默认阉割了。找不到函数体,所以编译器还不报错,蛋疼。 实现代码:
//重定向函数 #inclde
这样就可以这么使用printf(“I hate it here%d%f”,x,y);通过串口打印到电脑上的串口助手,方便调试
//程序代码:
GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; //打开GPIO时钟和USART模块时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
//配置GPIO管脚模式,包括TX和RX,TX一般为复用推挽输出,RX为浮空输入 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA,&GPIO_InitStructure);
//配置USART参数,包括数据位、波特率、停止位、校验位等 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_Tx | USART_Mode_Rx; USART_Init(USART1, &USART_InitStructure); //使能USART
USART_Cmd(USART1,ENABLE);
USART_SendData(USART1, (unsigned char)ch);
while (USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); return (ch);
发送后检测,接收前检测 发送数据:
USART_SendData(USARTx,message[index]);
while(USART_GetFlagStatus(USARTx,USART_FLAG_TXE) == RESET);//检测是否发送完成再发下一数据,不是上一条语句执行完就发完了,不然会漏数据,还有可能丢掉标志位,死在中断里,吃过亏
接收数据: (查询方式)
while(USART_GetFlagStatus(USARTx,USART_FLAG_RXNE) != SET);
receive = (u8)USART_ReceiveData(USART1);//函数返回的是16位数据,高8位全零 (中断方式)
//。。。配置完管脚、模式什么的 //中断配置
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);