外接CH340,在电脑端安装好CH340驱动,连接电脑,通过电脑的串口助手发送学号点亮对应LED灯,发送姓名熄灭LED灯。
接收函数、比较函数要求自己撰写。(不然可以通过调用strcmp函数即可)
1、main.c部分:
#include "stm32f10x.h" // Device header
#include <string.h>
#include "Delay.h"
#include "LED.h"
#include "Serial.h"
char * xuehao = "202078057912";
char * name = "张三";
int main(void)
{
LED_Init();
LED2_OFF();
Serial_Init();
send_string("Hello\r\n");
while(1)
{
if (Compare_arrays_to_strings(recv_data_buff, xuehao) == 1)//判断两个字符串是否相等(如果相等会返回0)
{
LED1_ON();
}
if (Compare_arrays_to_strings(recv_data_buff, name) == 1)//判断两个字符串是否相等(如果相等会返回0)
{
LED1_OFF();
}
}
}
2、Serial.c部分
#include "stm32f10x.h" // Device header
#include <stdio.h>
#include <stdarg.h>
#include "led.h"
void Serial_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); //开启时钟
//初始化GPIOA引脚
GPIO_InitTypeDef GPIO_InitStructure; //定义一个结构体变量
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //GPIO模式:复用推挽输出(供USART的TX使用)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //用到GPIO9号口
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO的速度
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOA外设,结构体变量名取地址(地址传递)
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //GPIO模式:浮空输入模式(供USART的RX使用)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //用到GPIO10号口
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO的速度
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化GPIOA外设,结构体变量名取地址(地址传递)
//一般RX配置是浮空输入或上拉输入,因为串口波形空闲状态是高电平,所以不使用下拉输入
//配置USART初始化
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 9600; //波特率(Init函数内部会自动算好9600对应的分频系数,然后写入BRR寄存器)
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //硬件流控制(不使用流控)
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; //串口模式(发送和接受)
USART_InitStructure.USART_Parity = USART_Parity_No; //校验位(无校验)
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位(一位停止位)
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长(8位)
USART_Init(USART1, &USART_InitStructure);
//对于串口接收来说,可以使用查询和中断两种方法,如果使用查询,初始化到这里就可以了
//用中断的方法(需要开启中断)
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启RXNE标志位到NVIC的输出(RXNE标志位一但置1,就会向NVIC申请中断)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //分组
//初始化NVIC的USART1的通道
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //中断通道
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init( &NVIC_InitStructure);
USART_Cmd(USART1, ENABLE);
}
void Send_Byte(uint8_t res)
{
USART_SendData(USART1,res);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == 0);
}
void send_string(char * data)
{
uint8_t i = 0;
while(data[i] != '\0')
{
Send_Byte(data[i]);
i ++;
}
}
uint8_t sta_rea_flag,sta_flag;
uint8_t end_rea_flag,end_flag;
char recv_data_buff[50];
uint16_t recv_data_point;
void USART1_IRQHandler(void)
{
uint8_t res = 0;
if(USART_GetITStatus(USART1, USART_IT_RXNE) == SET)//判断标志位
{
res = USART_ReceiveData(USART1);
if (sta_flag != 1) //判断包头
{
if (sta_rea_flag == 1)
{
if (res == 0xff)
{
sta_flag = 1;
for(int i = 0;i < recv_data_point; i ++)
recv_data_buff[i] = 0;
recv_data_point = 0;
}
else
sta_rea_flag = 0;
}
else if (res == 0xff)
sta_rea_flag = 1;
}
else
{
if (end_flag != 1) //判断包尾
{
if (end_rea_flag == 1)
{
if (res == '\n')
{
end_flag = 0;
end_rea_flag = 0;
sta_flag = 0;
sta_rea_flag = 0;
}
else
end_rea_flag = 0;
}
else if (res == '\r')
end_rea_flag = 1;
else
{
recv_data_buff [recv_data_point] = res;
recv_data_point ++;
}
}
}
//是否要手动清除标志位要参考手册,这里如果读取了DR就可以自动清除,没读取就要手动
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}
}
int16_t Compare_arrays_to_strings(char *a,char *b)
{
int i = 0;
if(a[i] != 0)
{
do
{
if( a[i] == *(b+i))
{
i++;
}
else if( a[i] != *(b+i))
return 0;
if((a[i] == 0) && (b[i] != 0))
return 0;
if((a[i] != 0) && (b[i] == 0))
return 0;
}while((a[i] != 0) && (b[i] != 0));
return 1;
}
return 0;
}
3、LED.c文件
#include "stm32f10x.h" // Device header
#include "Delay.h"
void LED_Init(void) //LED初始化函数
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG, ENABLE); //APB2外设时钟控制(接在GPIOA上,使能)
GPIO_InitTypeDef GPIO_InitStructure; //定义一个结构体变量
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式:推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_8; //用到GPIO1、2号口
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO的速度
GPIO_Init(GPIOG,&GPIO_InitStructure); //初始化GPIOA外设,结构体变量名取地址(地址传递)
GPIO_SetBits(GPIOG, GPIO_Pin_6 | GPIO_Pin_8); //GPIOA 1、2口设置为高电平
}
void LED1_ON(void)
{
GPIO_ResetBits(GPIOG,GPIO_Pin_6);
}
void LED1_OFF(void)
{
GPIO_SetBits(GPIOG,GPIO_Pin_6);
}
void LED1_Turn(void)
{
if(GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6)==0) //读取现在的输出值
{
GPIO_SetBits(GPIOG, GPIO_Pin_6);
}
else
{
GPIO_ResetBits(GPIOG,GPIO_Pin_6);
}
Delay_ms(10);
}
void LED2_ON(void)
{
GPIO_ResetBits(GPIOG,GPIO_Pin_8);
}
void LED2_OFF(void)
{
GPIO_SetBits(GPIOG,GPIO_Pin_8);
}
void LED2_Turn(void)
{
if(GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_8)==0)
{
GPIO_SetBits(GPIOG, GPIO_Pin_8);
}
else
{
GPIO_ResetBits(GPIOG,GPIO_Pin_8);
}
}
其他.h文件自己创建即可,或者都放在main.c文件里也可以,不需要其他文件。