
在main.c里- h4 ]. P+ D+ [9 ? /* USER CODE BEGIN PV *// U5 D# V7 B5 w( J9 X+ O0 z( }; [; h /* Private variables ---------------------------------------------------------*// J) B% R4 \4 ~7 z1 o uint8_t transmit[3] ={1,2,3}; //定义8位数组,3个字节大小 7 e. d u9 k% H% r uint16_t len =3; uint32_t timeout =10; /* USER CODE END PV */ / }$ T* k$ I/ V main(){ HAL_UART_Transmit(&huart1, transmit,len, timeout); while (1) {}7 K# @4 t$ h4 O7 \- Q3 J4 h9 f5 x }2 v7 Q: K" {/ L% ] 复位键启动程序,上位机接收到01 02 036 b) p/ M, r' ]' p8 k6 u0 C 关于timeout,它在HAL_UART_Transmit()里和uwTick做比较, L* v! c7 x) [6 T% Y uwTick是全局变量,在中断函数SysTick_Handler()里一直循环递增 可在main.c>>SystemClock_Config(void)里找到HCLK/1000+ o$ b8 S& A, p( _! {8 p: d" Z HCLK/1000就是中断进SysTick_Handler()的次数 你的CPU有1000分之一时间都在做uwTick++; HCLK是什么?请看附件图: @/ ]5 J3 h+ [( }3 ? ! d8 A7 I' P& c4 C N timeout的意义: timeout就是等待上一字符发送完毕,或异常退出 . N& ]; K1 |8 V; q# }2 n uint8_t string[123] ={0}; //这个数组很长/ ^- k8 T O$ j1 E# W HAL_UART_Transmit(&huart1, transmit,len, timeout); //假设timeout=10;顺利从UART1发出% S; R9 `& j$ g/ B$ v i3 z HAL_UART_Transmit(&huart2, transmit,len, timeout); //timeout=10;够长,顺利从UART2发出 2 G/ L" i0 {, `4 v 关于传送完毕,有人用如下方法等待传送完毕0 ]5 _& A, w( T7 I a! d 虽然方案可行) x) m; }) p( k( i l while(HAL_OK !=HAL_UART_Transmit(&huart2, transmit,len, timeout)); 这容易卡死,卡死都不知道8 {4 O7 q+ l6 p$ z) I% U 做产品应该尽量避免错误 . q" I' j H. b$ g0 r. L! I 很明显timeout提供一种方法(针对所有用到timeout的函数) 根据数组长度,根据波特率大小,根据处理器速度,根据中断资源的支配# s" \6 R8 r- p; j 适当增加timeout ,或减小timeout 会节约系统开支或保证系统运行的稳定性: J; p& i6 z X7 M7 S% H4 S 不会丢数据- M; h' O9 ` }/ U% T8 Q' G 使用while有几个弊端,不仅程序写的难看 万一,HAL_UART_Transmit()返回的不是HAL_OK而是HAL_TIMEOUT,程序卡死在这里都不知道 作为程序员,自己写的程序的运行次数和运行时间一定要牢记在心的 9 U' F* I7 i! N' }7 q / p( M- N9 }* h& E) n* x. E HAL_UART_Transmit()用起来简单,全局可用 U% C0 X1 I, c% _6 [, d 只是编程思想上要和HAL库统一起来' w8 ?: x. K8 D( e- ?: k uint32_t transmit[3] ={1,2,3}; //发送的数组最好不要像这样定义成32位的 根据C语言,名字"transmit"就是32位指针. B9 H. t+ N+ Z uint8_t transmit[3] ={1,2,3}; //定义成这样8位的 根据C语言,名字"transmit"就是8位指针对应于形参uint8_t *pData HAL_UART_Transmit(UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size, uint32_t Timeout) ( t5 f; j3 R( ?- [6 b a; ?0 ~# Y stm32cubemx很重要的思想就是:/*USER CODE BEGIN*/ 。。。//在KEIL中编辑* [0 R: N, B/ Z7 i, ~; }% ^ /*USER CODE END*/ 代码一定!!!要放在这之间,可以用MDK和cubeMX两个软件同时!!!对代码进行更新" U T' a4 v& J 假设当你程序写UART完了,又需要添加新外设TIM1时可以用CUBEMX添加新外设 在CUBEMX软件中点击Project Generate Code CUBEMX软件不会改变/*USER CODE BEGIN*/ 到 /*USER CODE END*/之间的代码 环境:STM32CUBEMX,MDK-4 硬件:STM32F405RGTx,LQFP64封装 UART1:A9和A10 简单的UART代码就没必要上传了吧, f5 E U7 s+ g' m$ C( g+ y4 d 0 ?0 m) r4 X' Z, o; d |
HCLKå¨cubemxéæçè§
(0)你的数组长度有上限,每组数组传输时间应该也有上限
(1)假设你在main()函数中有用hal_uart_transmit()传数组,这时来了一个更高级的中断(或者某个异常),如果这个中断(或异常)耗时太长,timeout太短就会丢数据。timeout够长,ha_uart_transmit()就会等待等到中断函数(或异常)结束,再继续传数据,所以timeout和你的中断耗时(异常耗时)有一定关系,timeout其实就是“等待”的意思.* ^" R2 `1 V5 G( J; p
(2)如果你传递任意长数组,每一组数传递时间间短(在ms级别)的话,可以考虑加大(如timeout =100000;) n% H% S4 w7 Q/ I
用公式 等待时长 =timeout/(hclk/1000)单位秒 计算你需要的时长(timeout最大0xffff ffff 42亿多)
(4)建议按照严格的传输协议传数据,不要写容易卡死的程序,写能处理异常的程序才是好程序
不会去用这句话吧?官方的demo是这样的
if(HAL_OK !=HAL_UART_Transmit(&huart2, transmit,len, timeout))
{- A, U+ Y6 \; l
....................
} 3 A" A6 @5 G: t6 O5 h6 U
我觉得 不会有人去那么白痴的去写while的、