三、串口收发
目标:
前边工程写的震动LED亮一秒依然有效,但不能影响串口对灯的控制
上电串口向PC机发送 “hello usart”,
PC机发送’O’ led灯打开,返回"ON OK",
PC机发送’C’ led灯熄灭,返回"OFF OK",
如果PC机发送其他字符,返回"ERROR".
串口对灯的控制权应该比震动传感器大
引脚:
PA9 :TX
PA10:RX
步骤:
1、创建文件
在工程目录下边创建usart.c和usart.h两个文件
2、编写代码
usart.c
#include "usart.h"
#include "stm32f10x.h"
void usart_init(void)
{
GPIO_InitTypeDef usart_gpio_init; //声明配置PA9:TX,和PA10:RX的结构体
USART_InitTypeDef usart_init; //声明配置串口usart1的结构体
NVIC_InitTypeDef usart_nvic_init;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA的时钟(PA9:USART1_TX,PA10:USART1_RX)
RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE); //使能引脚复用时钟
RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1, ENABLE);//使能usart1时钟
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置优先级组
//配置PA9 TX的结构体
usart_gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
usart_gpio_init.GPIO_Pin = GPIO_Pin_9;
usart_gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &usart_gpio_init); //初始化PA9
//配置PA10 RX的结构体
usart_gpio_init.GPIO_Mode = GPIO_Mode_IN_FLOATING;
usart_gpio_init.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &usart_gpio_init); //初始化PA10
//配置串口usaet1的结构体
usart_init.USART_BaudRate = 115200;
usart_init.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
usart_init.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;
usart_init.USART_Parity = USART_Parity_No;
usart_init.USART_StopBits = USART_StopBits_1;
usart_init.USART_WordLength = USART_WordLength_8b;
USART_Init(USART1, &usart_init ); //初始化串口配置
//打开串口
USART_Cmd(USART1, ENABLE);
//配置NVIC(中断控制器)(用中断的方式接收PC机的数据)
usart_nvic_init.NVIC_IRQChannel = USART1_IRQn;
usart_nvic_init.NVIC_IRQChannelCmd = ENABLE;
usart_nvic_init.NVIC_IRQChannelPreemptionPriority = 1;
usart_nvic_init.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&usart_nvic_init);
//使能usart1中断
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
}
//封装发送字符串的函数
void Send_String(char *P)
{
while(*P != '\0')
{
USART_SendData(USART1,*P++); //发送一个字节
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
}
}
//重定向printf函数,使用printf就可以输出到串口上(不需要声明)
int fputc(int ch,FILE *f)
{
USART_SendData(USART1,(unsigned int)ch); //发送数据
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //等待发送结束
return ch;
}
//重定向scanf函数,(不需要声明)
int fgetc(FILE *f)
{
//等待接收完
while(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == RESET);
return (int)USART_ReceiveData(USART1); //返回接收到的数据
}
usart.h
#include "stdio.h"
//#include "stm32f10x.h"
void usart_init(void);
void Send_String(char *P);
main.c改为:
#include "stm32f10x.h"
#include "main.h"
#include "led.h" //引入LED相关的文件
#include "exti.h" //加入刚写的外部中断相关文件
#include "usart.h" //加入串口相关文件
char buff; //用来接收PC机发送的数据
void delay(uint16_t time)
{
uint16_t i = 0;
while(time--)
{
i = 8000;
while(i--);
}
}
int main()
{
LED_Init(); //初始化LED(PC13引脚)
Exti_Init(); //初始化外部中断1
usart_init(); //初始化串口usart1
GPIO_SetBits(GPIOC,GPIO_Pin_13); //让LED上电的时候熄灭
Send_String("hello usart"); //上电发送"hello usart"
//空循环,等待中断
while(1)
{
}
}
//串口接收的中断函数
void USART1_IRQHandler()
{
if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET) //如果接收标志位为SET,则接收完成
{
buff = (char)USART_ReceiveData(USART1); //将数据读到buff变量中
if( buff == 'O'){
GPIO_ResetBits(GPIOC,GPIO_Pin_13); //开灯
Send_String("ON OK\r\n"); //返回相关字符
}else if(buff == 'C'){
GPIO_SetBits(GPIOC,GPIO_Pin_13); //关灯
Send_String("OFF OK\r\n");
}else{
Send_String("ERROR\r\n");
}
}
}
//外部中断1服务函数
void EXTI1_IRQHandler(void)
{
if( EXTI_GetITStatus( EXTI_Line1) != RESET ) //如果中断标志位不是低电平(当PA1有下降沿时,触发中断)
{
GPIO_ResetBits(GPIOC,GPIO_Pin_13); //PC13拉低,点亮LED灯
delay(1000); //延时1000ms
if(buff != 'O'){ //震动传感器不能影响串口对灯的控制
GPIO_SetBits(GPIOC,GPIO_Pin_13); //PC13拉高,熄灭LED灯
}
EXTI_ClearFlag( EXTI_Line1); //清除标志位,等待下一次中断
}
}
3、编译烧录
使用FlyMcu.exe烧录程序
4、打开串口调试助手
发送’O’,‘C’,和其他字符,观察现象;