再次回顾之前的小项目:​​https://github.com/GreyZhang/printf_via_CAN​

         前面增加的Arduino例子可以看得出最后的版本工作是没问题的,但是这个是不是就是最好的呢?其实不然。为什么呢?printf的核心映射实现是putc的接口,在这个模块中我们改成了另一个名称。这个功能实现的是一个字符的操作,那么如何实现一个字节到CAN的多字节转换呢?在这里,我们引入的其实是一个队列的机制。

         在之前的代码中,队列机制其实是实现了的。但是,采用的算法比较凌乱,存储的操作过多。正好最近学习J1939,看到了别人的队列实现方式比我的好。于是,借用他的模式进行了这个版本的改进。

         核心的代码实现如下:

#define CAN_PRINTF_TX_QUEUE_LENGTH 128

uint8_t can_printf_chars_queue[CAN_PRINTF_TX_QUEUE_LENGTH];
uint8_t can_printf_queue_tail = 0x0U;
uint8_t can_printf_queue_head = 0x0U;
uint8_t can_printf_chars_num = 0U;


uint8_t can_printf_en_queue(uint8_t c)
{
if(can_printf_chars_num >= CAN_PRINTF_TX_QUEUE_LENGTH)
{
return ERR_QUEUE_FULL;
}

can_printf_chars_queue[can_printf_queue_tail] = c;
can_printf_queue_tail = (can_printf_queue_tail + 1) % CAN_PRINTF_TX_QUEUE_LENGTH;
can_printf_chars_num += 1U;

return ERR_OK;
}

uint8_t can_printf_de_queue(uint8_t *p_c)
{
if(can_printf_chars_num == 0U)
{
return ERR_QUEUE_EMPTY;
}

*p_c = can_printf_chars_queue[can_printf_queue_head];
can_printf_queue_head = (can_printf_queue_head + 1U) % CAN_PRINTF_TX_QUEUE_LENGTH;
can_printf_chars_num -= 1U;

return ERR_OK;
}

         比起我自己的实现方式来说,不仅仅是精简而且比较容易懂。其实,这个队列的实现,还可以把队列元素的个数给去掉,但是我觉得那样可读性稍差,暂时保留这个一个信息吧。队列索引值的处理,学习了2515库文件中的队列发送,也是现炒现卖。

         运行效果如下:

366_printf via CAN队列改进_#define


         效果还是可以的。开卷有益,多看看别人的代码其实也很有益!