【蓝牙小程序】STC8H接收蓝牙串口数据并解析的代码实现
问:STC8H接收蓝牙串口的数据,数据为字母+数字的形式,字母代表模式,数字为整数,并赋值给一个变量,请问这段代码怎么写?
下面是一个完整的STC8H单片机接收蓝牙串口数据并解析的代码示例,数据格式为"字母+数字"(如"A123"),字母代表模式,数字为整数并赋值给变量。
完整代码实现
#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(8位UART,可变波特率)
-
设置波特率为9600(可根据蓝牙模块实际波特率调整)
-
开启串口中断
-
-
数据接收:
-
使用中断方式接收数据
-
假设数据以回车换行("\r\n")结束
-
接收到完整数据后设置标志位
-
-
数据解析:
-
第一个字符为模式字母(A-Z)
-
后续字符为数字字符串,转换为整数
-
示例支持如"A123"、"B456"等格式
-
-
数据处理:
-
将模式字母存入
mode变量 -
将数字部分转换为整数存入
value变量 -
可根据不同模式执行不同操作
-
-
回显功能:
-
将解析结果通过串口发送回去(可选)
-
使用示例
-
通过蓝牙发送:"A123\r\n"
-
单片机将:
-
设置 mode = 'A'
-
设置 value = 123
-
返回:"Mode: A, Value: 123"
-
注意事项
-
根据实际蓝牙模块调整波特率(常见的有9600、115200等)
-
如果数据格式不同(如无结束符),需要修改接收逻辑
-
增加数据校验机制可以提高可靠性
-
长数据接收时注意缓冲区溢出保护
-
实际应用中可能需要添加超时处理机制
您可以根据实际需求修改此代码,例如添加更多模式处理或改变数据格式解析方式。
扩展:C51单片机是否可以使用atoi()函数
在C51单片机编程中,是否可以使用标准C库的atoi()函数取决于您使用的编译器和库支持情况。
情况分析
1. Keil C51编译器
可以使用atoi()函数,但需要注意以下几点:
-
需要包含
stdlib.h头文件 -
该函数会占用一定的代码空间(约200-300字节)
-
在小型51单片机中使用时要注意ROM空间是否足够
示例代码:
#include <stdlib.h> // 包含atoi()函数声明
void main() {
char str[] = "123";
int num;
num = atoi(str); // 将字符串转换为整数
// 现在num = 123
}
2. 替代方案(节省空间)
如果ROM空间紧张,可以自己实现一个简单的字符串转整数函数:
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. 注意事项
-
负数处理:标准
atoi()支持负数,但上述简易实现不支持 -
溢出问题:51单片机int通常是16位,最大值为32767
-
错误处理:标准
atoi()对非法输入的处理是未定义行为
4. 完整示例(STC8H接收蓝牙数据并转换)
结合您之前的蓝牙接收需求:
#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()会更方便。

浙公网安备 33010602011771号