C Atmega328P String 到 Int 转换 block RX 中断

标签 c string type-conversion microcontroller interrupt

我使用 Atmega328P µC 通过 UART 获取字符串并将其转换为 int

我尝试使用atoi()函数或sscanf()来转换它,但它们需要很长时间才能转换,因此它们会阻塞中断。

如果我停止转换并仅通过 UART 接收,则所有符号都会传输,但如果我在接收后进行转换,则会丢失一些传输字符。

有什么方法可以加快转换速度以停止阻塞 RX 中断吗?

最佳答案

如果您需要将多字符数字转换为整数,则需要使用缓冲区。循环缓冲区使用示例:

#define BUF_LEN    128
#define BUF_MSK    (BUF_LEN-1)

uint8_t buf[BUF_LEN], b_in = 0, b_out = 0;

void usart_irq_handler(void)
{
    buf[b_in&BUF_MSK] = USART_DATA_REG;
    b_in++;
}

int main(void)
{
    uint8_t tmp;
    while (b_in!=b_out) {
        tmp = buf[b_out&BUF_MSK];
        b_out++;
        // parse here
    }
}

如果您需要转换单个字符数字,您可以不使用缓冲区(但如果 USART 频率不低于 CPU 频率,则不建议使用)。对于 ASCII 编码的接收字符,每个数字的值为 0x30..0x39。如果收到使用其他字符集编码的字符,您需要引用他们的表。

uint8_t num  = USART_DATA_REG - 0x30;
if (num >= 0 && num <= 9) {
    // is number
}

编辑1 [由于来自OP的新信息] 为了将十进制数从字符串转换为整数我使用这个函数:

uint32_t parse_num(uint8_t * ptr) 
{
    uint32_t res = (uint32_t)0x0;
    uint8_t chr = 0x0, pchr = 0xA;
    while (*ptr != (uint8_t)0x0) {
        chr = (uint8_t)(*ptr - (uint8_t)0x30);
        if (chr < 0xA) {
            res *= (uint32_t) 0xA;
            res += (uint32_t) chr;
        } else {
            if (pchr < 0xA) break;
        }
        pchr = chr;
        ptr++;
    }
    return res;
}

它跳过非数字字符并转换第一个找到的数字,但不返回解析缓冲区的最终位置。您可以根据需要进行修改。

编辑2 [由于与OP聊天] 关于处理器时间管理的好方法:

下面的图片(来自此answer)说明了程序中的正常处理器时序:

programm flows priorities

programm time

因此,中断处理程序时间越短 - 其他处理程序成功的可能性就越大,执行主流程的时间就越多。

通过增加 MCU 时钟可以减少代码的运行时间并增加空闲时间。

通过减少外围时钟可以降低外围中断的频率并增加空闲时间。

总之必须利用空闲时间来节省电量

关于C Atmega328P String 到 Int 转换 block RX 中断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36886920/

相关文章:

c - C中的双向链表排序函数

c++ - 不同 Makefile 目标的不同变量集

检查字符串中的字符是否是字母、数字或特殊字符。在c中

c - 打印字符串数组的部分内容

python - 替换数据框中格式不正确的值

我可以使用 C-preprocssor 将整数转换为字符串吗?

c - 包含单词链表的哈希表 C

java - 将多个用户输入的整数转换为字符串

C# Stream 写入 Uint 数组

c++ - 通过 C++ 中的预处理器定义构建不同的数据类型