【蓝牙小程序】STC8H接收蓝牙串口数据并解析的代码实现

问:STC8H接收蓝牙串口的数据,数据为字母+数字的形式,字母代表模式,数字为整数,并赋值给一个变量,请问这段代码怎么写?

下面是一个完整的STC8H单片机接收蓝牙串口数据并解析的代码示例,数据格式为"字母+数字"(如"A123"),字母代表模式,数字为整数并赋值给变量。

完整代码实现

c
复制
#include "stc8h.h"
#include <string.h>
#include <stdlib.h>

#define BUF_LEN 16  // 接收缓冲区长度

// 全局变量
unsigned char UART_RX_BUF[BUF_LEN];  // 接收缓冲区
unsigned char UART_RX_CNT = 0;       // 接收计数器
bit UART_RX_Complete = 0;            // 接收完成标志

char mode = ' ';     // 存储模式字母
int value = 0;       // 存储解析出的整数值

// 串口初始化
void UART_Init(void)
{
    SCON = 0x50;        // 8位数据,可变波特率,允许接收
    AUXR |= 0x40;       // 定时器1时钟为Fosc,即1T
    AUXR &= 0xFE;       // 串口1选择定时器1为波特率发生器
    TMOD &= 0x0F;       // 清除定时器1模式位
    TMOD |= 0x20;       // 设定定时器1为8位自动重装方式
    TL1 = 0xE8;         // 设定定时初值(波特率9600)
    TH1 = 0xE8;         // 设定定时器重装值
    ET1 = 0;            // 禁止定时器1中断
    TR1 = 1;            // 启动定时器1
    
    ES = 1;             // 允许串口中断
    EA = 1;             // 开总中断
}

// 发送一个字节
void UART_SendByte(unsigned char dat)
{
    SBUF = dat;
    while(!TI);
    TI = 0;
}

// 发送字符串
void UART_SendString(unsigned char *str)
{
    while(*str != '\0')
    {
        UART_SendByte(*str++);
    }
}

// 串口中断服务函数
void UART_Isr() interrupt 4
{
    if(RI)
    {
        RI = 0; // 清除接收中断标志
        
        // 接收数据并判断是否结束(假设以回车换行结束 "\r\n")
        unsigned char ch = SBUF;
        
        if(ch == '\n' || UART_RX_CNT >= BUF_LEN-1)
        {
            // 收到结束符或缓冲区满
            UART_RX_BUF[UART_RX_CNT] = '\0'; // 添加字符串结束符
            UART_RX_Complete = 1;            // 设置接收完成标志
            UART_RX_CNT = 0;                 // 复位计数器
        }
        else if(ch != '\r') // 忽略回车符
        {
            UART_RX_BUF[UART_RX_CNT++] = ch; // 存储接收到的字符
        }
    }
    
    if(TI)
    {
        TI = 0; // 清除发送中断标志
    }
}

// 解析接收到的数据
void ParseReceivedData(void)
{
    if(UART_RX_BUF[0] >= 'A' && UART_RX_BUF[0] <= 'Z')
    {
        mode = UART_RX_BUF[0]; // 获取模式字母
        
        // 提取数字部分并转换为整数
        char numStr[BUF_LEN-1];
        strncpy(numStr, &UART_RX_BUF[1], BUF_LEN-1);
        numStr[BUF_LEN-2] = '\0'; // 确保字符串结束
        
        value = atoi(numStr); // 字符串转整数
        
        // 可以在这里根据不同的模式执行不同的操作
        switch(mode)
        {
            case 'A':
                // 模式A的处理
                break;
            case 'B':
                // 模式B的处理
                break;
            // 其他模式...
            default:
                break;
        }
        
        // 发送回显信息(可选)
        UART_SendString("Mode: ");
        UART_SendByte(mode);
        UART_SendString(", Value: ");
        
        // 发送数值(需要将整数转换为字符串发送)
        char valStr[10];
        itoa(value, valStr, 10);
        UART_SendString(valStr);
        UART_SendString("\r\n");
    }
    else
    {
        UART_SendString("Invalid format!\r\n");
    }
}

void main()
{
    UART_Init();
    UART_SendString("STC8H Bluetooth UART Receiver Ready!\r\n");
    
    while(1)
    {
        if(UART_RX_Complete) // 如果收到完整数据
        {
            UART_RX_Complete = 0; // 清除标志
            
            // 解析数据
            ParseReceivedData();
        }
    }
}

代码说明

  1. 初始化部分

    • 配置串口为模式1(8位UART,可变波特率)

    • 设置波特率为9600(可根据蓝牙模块实际波特率调整)

    • 开启串口中断

  2. 数据接收

    • 使用中断方式接收数据

    • 假设数据以回车换行("\r\n")结束

    • 接收到完整数据后设置标志位

  3. 数据解析

    • 第一个字符为模式字母(A-Z)

    • 后续字符为数字字符串,转换为整数

    • 示例支持如"A123"、"B456"等格式

  4. 数据处理

    • 将模式字母存入mode变量

    • 将数字部分转换为整数存入value变量

    • 可根据不同模式执行不同操作

  5. 回显功能

    • 将解析结果通过串口发送回去(可选)

使用示例

  1. 通过蓝牙发送:"A123\r\n"

  2. 单片机将:

    • 设置 mode = 'A'

    • 设置 value = 123

    • 返回:"Mode: A, Value: 123"

注意事项

  1. 根据实际蓝牙模块调整波特率(常见的有9600、115200等)

  2. 如果数据格式不同(如无结束符),需要修改接收逻辑

  3. 增加数据校验机制可以提高可靠性

  4. 长数据接收时注意缓冲区溢出保护

  5. 实际应用中可能需要添加超时处理机制

您可以根据实际需求修改此代码,例如添加更多模式处理或改变数据格式解析方式。

 

 

扩展:C51单片机是否可以使用atoi()函数

在C51单片机编程中,是否可以使用标准C库的atoi()函数取决于您使用的编译器和库支持情况。

情况分析

1. Keil C51编译器

可以使用atoi()函数,但需要注意以下几点:

  • 需要包含stdlib.h头文件

  • 该函数会占用一定的代码空间(约200-300字节)

  • 在小型51单片机中使用时要注意ROM空间是否足够

示例代码:

c
复制
#include <stdlib.h> // 包含atoi()函数声明

void main() {
    char str[] = "123";
    int num;
    
    num = atoi(str); // 将字符串转换为整数
    // 现在num = 123
}

2. 替代方案(节省空间)

如果ROM空间紧张,可以自己实现一个简单的字符串转整数函数:

c
复制
unsigned int my_atoi(char *str) {
    unsigned int val = 0;
    
    while (*str) {
        if (*str >= '0' && *str <= '9') {
            val = val * 10 + (*str - '0');
            str++;
        } else {
            break; // 遇到非数字字符则停止
        }
    }
    
    return val;
}

3. 注意事项

  1. 负数处理:标准atoi()支持负数,但上述简易实现不支持

  2. 溢出问题:51单片机int通常是16位,最大值为32767

  3. 错误处理:标准atoi()对非法输入的处理是未定义行为

4. 完整示例(STC8H接收蓝牙数据并转换)

结合您之前的蓝牙接收需求:

c
复制
#include <STC8H.H>
#include <stdlib.h>
#include <string.h>

#define BUF_LEN 16
char UART_RX_BUF[BUF_LEN];
unsigned char UART_RX_CNT = 0;
bit UART_RX_Complete = 0;

void UART_Init() {
    // 串口初始化代码...
}

void UART_Isr() interrupt 4 {
    if(RI) {
        RI = 0;
        char ch = SBUF;
        
        if(ch == '\n' || UART_RX_CNT >= BUF_LEN-1) {
            UART_RX_BUF[UART_RX_CNT] = '\0';
            UART_RX_Complete = 1;
            UART_RX_CNT = 0;
        }
        else if(ch != '\r') {
            UART_RX_BUF[UART_RX_CNT++] = ch;
        }
    }
}

void main() {
    char mode;
    int value;
    
    UART_Init();
    
    while(1) {
        if(UART_RX_Complete) {
            UART_RX_Complete = 0;
            
            mode = UART_RX_BUF[0]; // 获取模式字符
            
            // 使用atoi转换后面的数字部分
            value = atoi(&UART_RX_BUF[1]);
            
            // 现在可以使用mode和value进行控制
            // ...
        }
    }
}

总结

  • 可以在C51中使用atoi(),但会占用较多空间

  • 对于简单应用,推荐自己实现转换函数以节省ROM空间

  • 在STC8H等增强型51单片机中,ROM空间通常足够,可以直接使用标准库函数

  • 注意处理数值范围和错误情况

如果项目对代码大小有严格要求,建议使用自定义转换函数;否则,直接使用atoi()会更方便。

posted @ 2025-04-03 09:56  FBshark  阅读(161)  评论(0)    收藏  举报