0.0

STM32F103 串口1和串口3对发数据 配合蓝牙模块 实现手机和单片机的简单通信demo

@

前言

开发板:正点原子 STM32F103 精英版
语言:C语言
开发环境:Keil5
使用了 KEY LED USART USB转TTL模块 智向的蓝牙模块(ps:电脑安装驱动CH340)
代码下载码云 GitHub
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414172334869.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

代码参考:正点原子 源码 串口实验例程
功能介绍
1、LED的0.2秒一闪,表示程序正在运行。
2、串口1收到的数据会发给串口3,串口3收到的数据会发给串口1。
3、按键KEY1按下会向串口1发送数据‘1’,按键KEY0按下会向串口3发送数据‘3’。

接线

USB转TTL

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414173024830.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414172832226.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414172918503.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

蓝牙

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414174608456.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414174715467.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414175008697.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

效果图

USB转TTL

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414172015329.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

蓝牙

使用的手机软件(安卓)为 BLE调试助手
在这里插入图片描述
打开软件、蓝牙、给予权限等
扫描到我们的蓝牙模块,然后连接
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414182506271.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
连接成功后
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414182541621.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
点击最下面的 Unkonwn Service,展开,有接收 和 发送 按钮
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414182643669.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

手机收 电脑发

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414183011609.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414183043610.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

手机发 电脑收

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414183059821.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414183111664.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

蓝牙的连接/断开

蓝牙收到了手机发来的 连接 和 断开 信息
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414183138426.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

参考用图

STM32F103

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414183358864.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414183457891.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/2021041418352852.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

蓝牙模块相关

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414171505592.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414171523504.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)
![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210414171602317.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

核心代码

完整代码下载码云 GitHub

main.c

#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart1.h"
#include "usart3.h"

// 串口收发函数 type为1,串口1收,发往串口3  type不为1,串口3,发往串口1
void usart_recv_send(u8 type);

int main(void)
{
    vu8 key = 0;
    delay_init();												 // 延时函数初始化
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    usart1_init(115200);									 // USART1初始化 波特率115200 默认数据位8 停止位1 校验位none
    usart3_init(115200);									 // USART3初始化 波特率115200 默认数据位8 停止位1 校验位none
    LED_Init();												 // LED端口初始化
    KEY_Init();										  	 	 // 初始化与按键连接的硬件接口
    while (1)
    {
        // 串口收发
        usart_recv_send(1);
        usart_recv_send(3);

        // 得到键值
        key = KEY_Scan(0);
        if (key)
        {
            switch (key)
            {
                case KEY1_PRES: // 向串口1发送'1'
                    usart1_send_byte(0x31);
                    break;
                case KEY0_PRES: // 向串口3发送'3'
                    usart3_send_byte(0x33);
                    break;
            }
        }

        LED0 = !LED0; //闪烁LED,提示系统正在运行.
        delay_ms(100);
    }
}

// 串口收发函数 type为1,串口1收,发往串口3  type不为1,串口3,发往串口1
void usart_recv_send(u8 type)
{
    u8 i = 0;
    u8 tmp_len = 0;
    // 数据缓存
    static u8 buf[255] = {0};
    // 数据长度
    u8 buf_len = 0;

    // 返回缓存区数据的个数
    if(1 == type)
        tmp_len = usart1_getdata_count();
    else
        tmp_len = usart3_getdata_count();

    for(i=0; i<tmp_len; i++)
    {
        // 返回缓存区当前指针所指数据
        if(1 == type)
            buf[i] = usart1_receive_data();
        else
            buf[i] = usart3_receive_data();

        buf_len++;
        // 超过约定的上限长度
        if(buf_len >= 250)
        {
            buf_len=0;
            break;
        }
    }

    // 数据不为空
    if(0 != buf_len)
    {
        // 串口数据发送
        if(1 == type)
            usart3_send_bytes(buf, buf_len);
        else
            usart1_send_bytes(buf, buf_len);
    }
}

usart1.c

#include "usart1.h"
#include "stdio.h"

static uint8_t usart1_buffer[255];
static uint8_t usart1_index;
static uint8_t usart1_count;

// USART1初始化 默认数据位8 停止位1 校验位none
void usart1_init(u32 bound)
{
    // GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* config USART1 clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能USART1,GPIOA时钟

    /* USART1 GPIO config */
    /* Configure USART1 Tx (PA.09) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.9
    /* Configure USART1 Rx (PA.10) as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.10

    // Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		//子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

    USART_InitStructure.USART_BaudRate = bound; // 串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长为8位数据格式
    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); // 初始化串口1
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口接受中断

    USART_Cmd(USART1, ENABLE); // 使能串口1

    usart1_index=0;
    usart1_count=0;
}

// 中断服务函数
void USART1_IRQHandler(void)
{
    // 接收中断
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        if(usart1_count==usart1_index)
        {
            // 缓存区无数据,回到起点开始存储
            usart1_count=0;
            usart1_index=0;
        }
        usart1_buffer[usart1_count]=USART1->DR;
        usart1_count++;
        if(usart1_count>=250)
        {
            // 没有及时取出数据,导致存储位置到达末尾,回到起点
            usart1_count=0;
            usart1_index=0;
        }
    }
}

/*返回缓存区数据的个数*/
uint8_t usart1_getdata_count(void)
{
    return usart1_count-usart1_index;
}

/*返回缓存区当前指针所指数据*/
uint8_t usart1_receive_data(void)
{
    return usart1_buffer[usart1_index++];
}

/*串口数据发送函数
data_send:发送数据
*/
void usart1_send_byte(uint8_t data_send)
{
    USART_SendData(USART1, data_send);
    while (!(USART1->SR & USART_FLAG_TXE));
}

/*串口数据发送函数
data_buffer:发送数据串的首地址
length:发送数据的长度
*/
void usart1_send_bytes(uint8_t* data_buffer,uint8_t length)
{
    uint8_t i;
    for(i=0; i<length; i++)
    {
        usart1_send_byte(data_buffer[i]);
    }
}

usart3.c

#include "usart3.h"
#include "stdio.h"

static uint8_t usart3_buffer[255];
static uint8_t usart3_index;
static uint8_t usart3_count;

// USART3初始化 默认 数据位8 停止位1 校验位none
void usart3_init(u32 bound)
{
	// GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* config USART3 clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); //使能USART3,GPIOB时钟

    /* USART3 GPIO config */
    /* Configure USART3 Tx (PB.10) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    /* Configure USART3 Rx (PB.11) as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		//子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

    USART_InitStructure.USART_BaudRate = bound; // 串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长为8位数据格式
    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(USART3, &USART_InitStructure); // 初始化串口3
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 开启串口接受中断

    USART_Cmd(USART3, ENABLE); // 使能串口3 

    usart3_index=0;
    usart3_count=0;
}

// 中断服务函数
void USART3_IRQHandler(void)
{
    if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
    {
        if(usart3_count==usart3_index)
        {
            //缓存区无数据,回到起点开始存储
            usart3_count=0;
            usart3_index=0;
        }
        usart3_buffer[usart3_count]=USART3->DR;
        usart3_count++;
        if(usart3_count>=250)
        {
            //没有及时取出数据,导致存储位置到达末尾,回到起点
            usart3_count=0;
            usart3_index=0;
        }
    }
}

/*返回缓存区数据的个数*/
uint8_t usart3_getdata_count(void)
{
    return usart3_count-usart3_index;
}

/*返回缓存区当前指针所指数据*/
uint8_t usart3_receive_data(void)
{
    return usart3_buffer[usart3_index++];
}

/*串口数据发送函数
data_send:发送数据
*/
void usart3_send_byte(uint8_t data_send)
{
    USART_SendData(USART3, data_send);
    while (!(USART3->SR & USART_FLAG_TXE));
}

/*串口数据发送函数
data_buffer:发送数据串的首地址
length:发送数据的长度
*/
void usart3_send_bytes(uint8_t* data_buffer,uint8_t length)
{
    uint8_t i;
    for(i=0; i<length; i++)
    {
        usart3_send_byte(data_buffer[i]);
    }
}

拓展应用

实现简单的账号认证,通过命令控制LED1和蜂鸣器的开关

功能介绍

手机连接蓝牙,发送登录命令login#admin#admin

login#用户名#密码#

在这里插入图片描述

登录成功后,发送控制命令

cmd#device#status#

最后发送登出命令cmd#login#out
在这里插入图片描述

效果图

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210429113041220.png?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

![在这里插入图片描述]( https://img-blog.csdnimg.cn/20210429112847819.jpg?x-oss-process=image/watermark ,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0lrYXJvc181MjE=,size_16,color_FFFFFF,t_70)

代码

main.c
#include "led.h"
#include "delay.h"
#include "key.h"
#include "sys.h"
#include "usart1.h"
#include "usart3.h"
#include "string.h"
#include "stdio.h"
#include "beep.h"

u8 login = 0;
u8 username[21] = "admin";
u8 password[21] = "admin";

// 串口收发函数 type为1,串口1收,发往串口3  type不为1,串口3收,发往串口1
void usart_recv_send(u8 type);
// 检查登录 传入收到的数据和数据长度 返回 0验证成功,1账号或密码错误,2数据超长
u8 check_login(u8* buf, u8 len);
/*
	函数功能: 命令解析
	传参:     收到的数据和数据长度
	命令格式: cmd#device#status#
	返回: 	   0不符合规则 1解析成功
*/
u8 cmd_analysis(u8* buf, u8 len);

int main(void)
{
    vu8 key = 0;
    delay_init();											 // 延时函数初始化
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); 		 // 设置NVIC中断分组2:2位抢占优先级,2位响应优先级
    usart1_init(115200);									 // USART1初始化 波特率115200 默认数据位8 停止位1 校验位none
    usart3_init(115200);									 // USART3初始化 波特率115200 默认数据位8 停止位1 校验位none
    LED_Init();												 // LED端口初始化
    KEY_Init();										  	 	 // 初始化与按键连接的硬件接口
	BEEP_Init();									  	 	 // 蜂鸣器初始化
	LED0 = 1;
    while (1)
    {
        // 串口收发
        usart_recv_send(1);
        usart_recv_send(3);

        // 得到键值
        key = KEY_Scan(0);
        if (key)
        {
            switch (key)
            {
				case KEY1_PRES: // 向串口1发送'1'
					usart1_send_byte(0x31);
					break;
				case KEY0_PRES: // 向串口3发送'3'
					usart3_send_byte(0x33);
					break;
            }
        }

        LED0 = !LED0; //闪烁LED,提示系统正在运行.
        delay_ms(100);
    }
}

// 串口收发函数 type为1,串口1收,发往串口3  type不为1,串口3收,发往串口1
void usart_recv_send(u8 type)
{
    u8 i = 0;
    u8 tmp_len = 0;
    // 数据缓存
    static u8 buf[255] = {0};
    //static u8 buf2[255] = {0};
    // 数据长度
    u8 buf_len = 0;

    // 返回缓存区数据的个数
    if(1 == type)
        tmp_len = usart1_getdata_count();
    else
        tmp_len = usart3_getdata_count();

    for(i=0; i<tmp_len; i++)
    {
        // 返回缓存区当前指针所指数据
        if(1 == type)
            buf[i] = usart1_receive_data();
        else
            buf[i] = usart3_receive_data();

        buf_len++;
        // 超过约定的上限长度
        if(buf_len >= 250)
        {
            buf_len=0;
            break;
        }
    }

    // 数据不为空
    if(0 != buf_len)
    {
        // 串口数据发送
        if(1 == type)
            usart3_send_bytes(buf, buf_len);
        else
        {
            usart1_send_bytes(buf, buf_len);
			printf("\r\n");
            // 如果没有登录
            if(0 == login)
            {
                // 检查登录
                if(0 == check_login(buf, buf_len))
                {
                    login = 1;
                    printf("登录成功\r\n");
                }
                else if(2 == check_login(buf, buf_len))
                {
                    printf("账号或密码超长\r\n");
                }
				else if(3 == check_login(buf, buf_len))
                {
                    printf("命令过短,请发送命令\"login#账号#密码#\"登录\r\n");
                }
                else
                {
                    printf("账号或密码错误,请发送命令\"login#账号#密码#\"登录\r\n");
                }
            }
            // 已经登录
            else
            {
				cmd_analysis(buf, buf_len);
            }
        }
    }
}

// 检查登录 传入收到的数据 返回 0验证成功,1账号或密码错误,2数据超长,3数据过短
u8 check_login(u8* buf, u8 len)
{
    u8 i = 0, j = 0;
    u8 str_username[21] = {0};
    u8 str_password[21] = {0};
	if(len < 9)
	{
		return 3;
	}
    // 登录命令
    if(buf[0] == 'l' && buf[1] == 'o' && buf[2] == 'g' && buf[3] == 'i' && buf[4] == 'n' && buf[5] == '#')
    {
        // 解析数据获取username和password 分隔符为'#'
        j = 0;
        i = 6;
        while(buf[i] != '#' && i < len)
        {
            // 数据超长
            if(j >= 20)
            {
                return 2;
            }
            str_username[j++] = buf[i++];
        }
        str_username[j] = '\0';

        j = 0;
        i++;
        while(buf[i] != '#' && i < len)
        {
            // 数据超长
            if(j >= 20)
            {
                return 2;
            }
            str_password[j++] = buf[i++];
        }
        str_password[j] = '\0';

        if(0 == strcmp((char *)str_username, (char *)username) && 0 == strcmp((char *)str_password, (char *)password))
        {
            return 0;
        }
        else
        {
            return 1;
        }
    }
    else
    {
        return 1;
    }
}

/*
	函数功能: 命令解析
	命令格式: cmd#device#status#
	返回: 	   0不符合规则 1解析成功
*/
u8 cmd_analysis(u8* buf, u8 len)
{
	u8 device[10] = {0};
	u8 status[6] = {0};
	u8 i = 0, j = 0;
	if(len < 7)
	{
		printf("命令过短\r\n");
		return 0;
	}
	
	// 命令格式校验
	if(buf[0] == 'c' && buf[1] == 'm' && buf[2] == 'd' && buf[3] == '#')
	{
		// 解析数据获取devicestatus 分隔符为'#'
        j = 0;
        i = 4;
        while(buf[i] != '#' && i < len)
        {
            // 数据超长
            if(j >= 9)
            {
				printf("device超长\r\n");
                return 0;
            }
            device[j++] = buf[i++];
        }
        device[j] = '\0';
		
		j = 0;
        i++;
        while(buf[i] != '#' && i < len)
        {
            // 数据超长
            if(j >= 5)
            {
				printf("status超长\r\n");
                return 0;
            }
            status[j++] = buf[i++];
        }
        status[j] = '\0';
		
		// LED1的命令 ON/OFF
		if(0 == strcmp((char *)device, "LED1"))
        {
			if(0 == strcmp((char *)status, "ON"))
			{
				LED1 = 0;
				printf("LED1打开\r\n");
				return 1;
			}
			else if(0 == strcmp((char *)status, "OFF"))
			{
				LED1 = 1;
				printf("LED1关闭\r\n");
				return 1;
			}
			else
			{
				printf("命令错误\r\n");
				return 0;
			}  
        }
		else if(0 == strcmp((char *)device, "BEEP"))
        {
			if(0 == strcmp((char *)status, "ON"))
			{
				BEEP = 1;
				printf("BEEP打开\r\n");
				return 1;
			}
			else if(0 == strcmp((char *)status, "OFF"))
			{
				BEEP = 0;
				printf("BEEP关闭\r\n");
				return 1;
			}
			else
			{
				printf("命令错误\r\n");
				return 0;
			}  
        }
		else if(0 == strcmp((char *)device, "login"))
        {
			if(0 == strcmp((char *)status, "out"))
			{
				login = 0;
				printf("账号登出\r\n");
				return 1;
			}
			else
			{
				printf("命令错误\r\n");
				return 0;
			}  
        }
		else
		{
			printf("命令错误\r\n");
			return 0;
		}
	}
	else
	{
		printf("命令错误\r\n");
		return 0;
	}
}



usart1.c
#include "usart1.h"
#include "stdio.h"

static uint8_t usart1_buffer[255];
static uint8_t usart1_index;
static uint8_t usart1_count;

//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 

// USART1初始化 默认数据位8 停止位1 校验位none
void usart1_init(u32 bound)
{
    // GPIO端口设置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* config USART1 clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); // 使能USART1,GPIOA时钟

    /* USART1 GPIO config */
    /* Configure USART1 Tx (PA.09) as alternate function push-pull */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure); // 初始化GPIOA.9
    /* Configure USART1 Rx (PA.10) as input floating */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
    GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.10

    // Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		//子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器

    USART_InitStructure.USART_BaudRate = bound; // 串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长为8位数据格式
    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); // 初始化串口1
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); // 开启串口接受中断

    USART_Cmd(USART1, ENABLE); // 使能串口1

    usart1_index=0;
    usart1_count=0;
}

// 中断服务函数
void USART1_IRQHandler(void)
{
    // 接收中断
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        if(usart1_count==usart1_index)
        {
            // 缓存区无数据,回到起点开始存储
            usart1_count=0;
            usart1_index=0;
        }
        usart1_buffer[usart1_count]=USART1->DR;
        usart1_count++;
        if(usart1_count>=250)
        {
            // 没有及时取出数据,导致存储位置到达末尾,回到起点
            usart1_count=0;
            usart1_index=0;
        }
    }
}

/*返回缓存区数据的个数*/
uint8_t usart1_getdata_count(void)
{
    return usart1_count-usart1_index;
}

/*返回缓存区当前指针所指数据*/
uint8_t usart1_receive_data(void)
{
    return usart1_buffer[usart1_index++];
}

/*串口数据发送函数
data_send:发送数据
*/
void usart1_send_byte(uint8_t data_send)
{
    USART_SendData(USART1, data_send);
    while (!(USART1->SR & USART_FLAG_TXE));
}

/*串口数据发送函数
data_buffer:发送数据串的首地址
length:发送数据的长度
*/
void usart1_send_bytes(uint8_t* data_buffer,uint8_t length)
{
    uint8_t i;
    for(i=0; i<length; i++)
    {
        usart1_send_byte(data_buffer[i]);
    }
}

posted @ 2021-09-23 11:23  Love丶伊卡洛斯  阅读(2313)  评论(0)    收藏  举报