【蓝牙小程序】STC单片机解析蓝牙数据:C51 调用 atoi()
背景
电子项目是一个有多种工作模式的, 基于STC51系列单片机的拉力器,比如测到一定拉力值,就让蜂鸣器鸣叫;或者坚持到一定的市场,就让蜂鸣器鸣叫。
之前是通过按键切换各种工作模式的;
最近几天,尝试在小程序中尝试通过蓝牙控制不同模式,因此需要设计一个蓝牙协议,传输的是文本 ASCII 码,但是需要解析为数字,因此就需要用atoi() 函数。
正文
在 C51(Keil C51)中调用 atoi() 函数需要引入 <stdlib.h> 头文件。
示例代码:
#include <stdlib.h> // 引入 atoi() 函数的声明
void main() {
char str[] = "1234";
int num = atoi(str); // 将字符串转换为整数
// ... 其他代码
}
注意事项:
-
C51 标准库支持:
Keil C51 的标准库提供了atoi()函数,但需要确保你的项目链接了标准库(默认情况下是自动链接的)。 -
替代函数:
如果遇到问题,也可以使用strtol()(同样在<stdlib.h>中),它提供更健壮的字符串转换功能:long num = strtol(str, NULL, 10); // 转换为 long 类型 -
内存限制:
C51 是面向 8051 单片机的嵌入式环境,使用标准库函数时要注意 ROM/RAM 的占用情况。
如果编译时提示 atoi 未定义,请检查 Keil 的库配置或确认是否包含了正确的头文件。
将字符串转换为32位整数的C51实现
在C51(8051单片机)中,将字符串转换为32位整数需要注意以下几点:
-
处理可能的符号(+/-)
-
跳过前导空白字符
-
处理数字字符('0'-'9')
-
检测溢出(32位有符号整数范围是-2147483648到2147483647)
-
处理无效输入
以下是完整的实现代码:
#include <ctype.h> // 用于isdigit()函数
#include <limits.h> // 用于INT_MAX和INT_MIN定义
// 定义32位整数的最大值和最小值
#define INT32_MAX 2147483647
#define INT32_MIN (-2147483647 - 1)
/**
* @brief 将字符串转换为32位有符号整数
* @param str 要转换的字符串
* @return 转换后的32位整数
*/
long str_to_int32(const char *str) {
long result = 0;
unsigned char negative = 0;
unsigned char c;
// 跳过前导空白字符
while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\f' || *str == '\v') {
str++;
}
// 检查符号
if (*str == '-') {
negative = 1;
str++;
} else if (*str == '+') {
str++;
}
// 处理数字字符
while ((c = *str++) != '\0') {
if (!isdigit(c)) {
break; // 遇到非数字字符,停止转换
}
c -= '0'; // 将字符转换为数字值
// 检查是否会导致溢出
if (negative) {
if (result < (INT32_MIN + c) / 10) {
return INT32_MIN; // 下溢
}
result = result * 10 - c;
} else {
if (result > (INT32_MAX - c) / 10) {
return INT32_MAX; // 上溢
}
result = result * 10 + c;
}
}
return result;
}
// 示例用法
void example_usage() {
char str1[] = "12345";
char str2[] = "-67890";
char str3[] = "2147483647"; // INT32_MAX
char str4[] = "-2147483648"; // INT32_MIN
char str5[] = " +123 abc"; // 带前导空格和后续非数字字符
long num1 = str_to_int32(str1);
long num2 = str_to_int32(str2);
long num3 = str_to_int32(str3);
long num4 = str_to_int32(str4);
long num5 = str_to_int32(str5);
// 在这里可以使用转换后的数值
}
代码说明
-
前导空白处理:函数首先跳过所有空白字符(空格、制表符等)。
-
符号处理:检查字符串是否以'+'或'-'开头,设置相应的符号标志。
-
数字转换:
-
逐个字符处理,直到遇到非数字字符或字符串结束
-
将字符转换为对应的数字值('0'→0, '1'→1等)
-
-
溢出检测:
-
在每次累加前检查是否会导致溢出
-
如果检测到溢出,返回相应的最大值或最小值
-
-
返回值:
-
成功转换返回对应的32位整数
-
溢出时返回INT32_MAX或INT32_MIN
-
注意事项
-
这个实现不处理浮点数,只处理整数
-
对于无效输入(如"abc123"),会返回0
-
在C51环境中,long类型通常是32位的,适合存储32位整数
-
如果需要更严格的错误处理,可以添加一个输出参数来指示转换状态
这个实现考虑了8051单片机的资源限制,避免了使用大内存缓冲区或复杂的库函数,适合在嵌入式环境中使用。
将字符串转换为无符号32位整数的C51实现
以下是修改后的将字符串转换为无符号32位整数(uint32_t)的C51实现。无符号32位整数的范围是0到4294967295(0xFFFFFFFF)。
#include <ctype.h> // 用于isdigit()函数
// 定义无符号32位整数的最大值
#define UINT32_MAX 4294967295UL
/**
* @brief 将字符串转换为无符号32位整数
* @param str 要转换的字符串
* @return 转换后的无符号32位整数
*/
unsigned long str_to_uint32(const char *str) {
unsigned long result = 0;
unsigned char c;
// 跳过前导空白字符
while (*str == ' ' || *str == '\t' || *str == '\n' || *str == '\r' || *str == '\f' || *str == '\v') {
str++;
}
// 检查是否有符号(无符号数不应有符号)
if (*str == '-') {
return 0; // 负数对于无符号数是无效的
}
if (*str == '+') {
str++; // 跳过正号
}
// 处理数字字符
while ((c = *str++) != '\0') {
if (!isdigit(c)) {
break; // 遇到非数字字符,停止转换
}
c -= '0'; // 将字符转换为数字值
// 检查是否会导致溢出
if (result > (UINT32_MAX - c) / 10) {
return UINT32_MAX; // 上溢
}
result = result * 10 + c;
}
return result;
}
// 示例用法
void example_usage() {
char str1[] = "12345";
char str2[] = "4294967295"; // UINT32_MAX
char str3[] = "123abc"; // 带后续非数字字符
char str4[] = "-123"; // 无效输入(负数)
char str5[] = " 987 "; // 带前导空格
unsigned long num1 = str_to_uint32(str1);
unsigned long num2 = str_to_uint32(str2);
unsigned long num3 = str_to_uint32(str3);
unsigned long num4 = str_to_uint32(str4);
unsigned long num5 = str_to_uint32(str5);
// 在这里可以使用转换后的数值
}
主要修改点
-
移除符号处理:无符号整数不接受负号,如果检测到负号直接返回0
-
修改溢出检测:只需检测上溢(无符号数不会下溢)
-
数据类型变更:使用
unsigned long代替long -
最大值定义:使用
UINT32_MAX(4294967295)代替INT32_MAX -
返回值处理:溢出时返回
UINT32_MAX,无效输入返回0
注意事项
-
无符号数不接受负值,任何负号都会导致函数返回0
-
前导空格仍然会被跳过
-
遇到非数字字符会停止转换
-
如果输入字符串表示的数字超过4294967295,函数会返回4294967295
-
空字符串或无效输入会返回0
这个实现保持了原始代码的简洁性,同时适应了无符号整数的特性,适合在8051单片机等资源受限的环境中使用。

浙公网安备 33010602011771号