USART通信无反应
1、拓展坞
嗯这一点我是属实没想到,拓展坞只能接一根用于串口的线。细细想来,拓展坞虽有多个USB口接其他线,却是从上位机(PC)的一个USB口引来的,也就是说硬件上就决定上位机一个接口只能用于一个串口的通信?实测是,仿真线与串口线接在同一个上位机接口,会让串口线(CH340)在上位机中找不到
总之,不要把串口通信的线和仿真的线连接在同一个拓展坞(即上位机的同一个接口)。
2,接线接错了
这一点我是最想吐槽的,查了好多资料硬是没有查出串口的线到底长什么样,又该怎么接。除非有人指导或是老师上课讲到这,发了相关资料,否则初学者单凭自己很容易混淆接线接口,比如把TTL、USART、COM之类的弄混了,也很容易认错线。
这一点就属于不讲很容易错,会了又觉得太简单而没必要发讲╮ (╯_╰)╭
如果是做过数电设计(FPGA)或是使用J-Link烧录的话,想必对它一定不会陌生。
3,无法打印
在GPIO引脚配好,USART初始化正确、串口助手配置也正确的情况下,仍然无法打印
如果你不使用Keil,使用其他IDE的话,那么重定向printf时,要重写的是_write,因为arm-gnu-ebi交叉工具链和keil的工具链对应的printf不同。而这里重写的是_write里的_io_putchar
需要添加stdio.h和usart相应头文件
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart3 , (uint8_t *)&ch, 1, 0xFFFF);// HAL,可自己换为标准外设库
return ch;
}
4,配置正确_打印1个字符却输出一堆乱码
这个问题相当诡异,情形是这样的:使用USART_SendData发送数据是正常的,但是一用printf就会发出一堆乱码。跟踪调试后发现,数组长度直接就1024,无论我发几个字母。
查了许久网上资料,却仅仅了解到arm-gnu-ebi交叉编译工具链关于printf的重定向需要重写_write或__io_putchar。
后来无意中想起来,从STM32CubeMX生成的代码中是没有_sbrk这个函数,当时就匆忙从网上摘抄了关于_sbrk的实现函数。于是现在嘛,开始怀疑_sbrk的实现有问题
_sbrk是要添加到SysCall.c里的函数
下面是网上摘抄的
void *_sbrk(int incr) {
(void) incr;
return NULL;
}
仔细看一看的话,显然是有问题的,这与白板函数无异。于是就训练了一会AI
我提供脚本、开发环境、设备芯片型号给它,让它生成实现函数,没想到还挺好用。至少不会打印乱码了。
#include <sys/types.h>
extern char _sdata; // 已初始化数据段的起始地址
extern char _edata; // 已初始化数据段的结束地址
extern char _end; // 未初始化数据段(.bss)的结束地址
caddr_t _sbrk(int incr) {
static char *heap_end = NULL;
char *prev_heap_end;
if (heap_end == NULL) {
heap_end = &_end; // 堆的起始地址通常是未初始化数据段的结束地址
}
prev_heap_end = heap_end;
// 检查是否有足够的内存来分配
if (heap_end + incr > (char *)(((uintptr_t)&_sdata + (uintptr_t)&_edata) & ~(sizeof(uintptr_t) - 1))) {
// 堆空间不足
return (caddr_t) -1;
}
heap_end += incr;
return (caddr_t) prev_heap_end;
}
(如果有条件的话,可以把Keil等其他非arm-gnu-ebi的IDE关于这个函数的实现代码扒过来)
下面是从一些工程的system.c里找到这个函数
void *_sbrk(ptrdiff_t incr)
{
extern uint8_t _end; /* Symbol defined in the linker script */
extern uint8_t _estack; /* Symbol defined in the linker script */
extern uint32_t _Min_Stack_Size; /* Symbol defined in the linker script */
const uint32_t stack_limit = (uint32_t)&_estack - (uint32_t)&_Min_Stack_Size;
const uint8_t *max_heap = (uint8_t *)stack_limit;
uint8_t *prev_heap_end;
/* Initialize heap end at first call */
if (NULL == __sbrk_heap_end)
{
__sbrk_heap_end = &_end;
}
/* Protect heap from growing into the reserved MSP stack */
if (__sbrk_heap_end + incr > max_heap)
{
errno = ENOMEM;
return (void *)-1;
}
prev_heap_end = __sbrk_heap_end;
__sbrk_heap_end += incr;
return (void *)prev_heap_end;
}
USART传输数据失败
1,问题描述
在不使用DMA时,分批次使用USART从上位机向stm32传输少量数据(256字节)时,stm32可以正常接收,一旦单次传输四五百数据时,就进入USART的ErrorHandler。
一开始使用的波特率是9600,后来下调至4800,但仍然出错,只不过上限拓展到700左右传输数据才失败。
2,原因
一般常说的USART串口通信,指的是异步串口通信,这种通信不适合大量数据的传输。
3,解决办法
把串口助手的传输文件由【连续传输】改为【……延时xxx ms】
然后把波特率改为115200(这个我也不知道原因,调高了反而可以正常传输了。要注意单片机也要设为相同的波特率)