【蓝牙小程序】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);  // 将字符串转换为整数
    // ... 其他代码
}

注意事项:

  1. C51 标准库支持
    Keil C51 的标准库提供了 atoi() 函数,但需要确保你的项目链接了标准库(默认情况下是自动链接的)。

  2. 替代函数
    如果遇到问题,也可以使用 strtol()(同样在 <stdlib.h> 中),它提供更健壮的字符串转换功能:

     
    long num = strtol(str, NULL, 10);  // 转换为 long 类型
  3. 内存限制
    C51 是面向 8051 单片机的嵌入式环境,使用标准库函数时要注意 ROM/RAM 的占用情况。

如果编译时提示 atoi 未定义,请检查 Keil 的库配置或确认是否包含了正确的头文件。

 

 

将字符串转换为32位整数的C51实现

在C51(8051单片机)中,将字符串转换为32位整数需要注意以下几点:

  1. 处理可能的符号(+/-)

  2. 跳过前导空白字符

  3. 处理数字字符('0'-'9')

  4. 检测溢出(32位有符号整数范围是-2147483648到2147483647)

  5. 处理无效输入

以下是完整的实现代码:

c
 
复制
 
下载
#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);
    
    // 在这里可以使用转换后的数值
}

代码说明

  1. 前导空白处理:函数首先跳过所有空白字符(空格、制表符等)。

  2. 符号处理:检查字符串是否以'+'或'-'开头,设置相应的符号标志。

  3. 数字转换

    • 逐个字符处理,直到遇到非数字字符或字符串结束

    • 将字符转换为对应的数字值('0'→0, '1'→1等)

  4. 溢出检测

    • 在每次累加前检查是否会导致溢出

    • 如果检测到溢出,返回相应的最大值或最小值

  5. 返回值

    • 成功转换返回对应的32位整数

    • 溢出时返回INT32_MAX或INT32_MIN

注意事项

  1. 这个实现不处理浮点数,只处理整数

  2. 对于无效输入(如"abc123"),会返回0

  3. 在C51环境中,long类型通常是32位的,适合存储32位整数

  4. 如果需要更严格的错误处理,可以添加一个输出参数来指示转换状态

这个实现考虑了8051单片机的资源限制,避免了使用大内存缓冲区或复杂的库函数,适合在嵌入式环境中使用。

 
 
 
 
 
将上述程序改为转变为无符号32位整数
 
 
 

将字符串转换为无符号32位整数的C51实现

以下是修改后的将字符串转换为无符号32位整数(uint32_t)的C51实现。无符号32位整数的范围是0到4294967295(0xFFFFFFFF)。

c
 
复制
 
下载
#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);
    
    // 在这里可以使用转换后的数值
}

主要修改点

  1. 移除符号处理:无符号整数不接受负号,如果检测到负号直接返回0

  2. 修改溢出检测:只需检测上溢(无符号数不会下溢)

  3. 数据类型变更:使用unsigned long代替long

  4. 最大值定义:使用UINT32_MAX(4294967295)代替INT32_MAX

  5. 返回值处理:溢出时返回UINT32_MAX,无效输入返回0

注意事项

  1. 无符号数不接受负值,任何负号都会导致函数返回0

  2. 前导空格仍然会被跳过

  3. 遇到非数字字符会停止转换

  4. 如果输入字符串表示的数字超过4294967295,函数会返回4294967295

  5. 空字符串或无效输入会返回0

这个实现保持了原始代码的简洁性,同时适应了无符号整数的特性,适合在8051单片机等资源受限的环境中使用。

posted @ 2025-04-11 14:16  FBshark  阅读(84)  评论(0)    收藏  举报