KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记7 - STM32的CAN学习与测试2

本文详细描述了使用KEIL5.38的ARM-CM3/4进行STM32的CAN模块测试,涉及单机回环模式、双机通讯发送的注意事项,以及如何处理发送错误和ACK错误。作者还分享了测试环境和关键代码段,以及后续的测试结果和计划。
摘要由CSDN通过智能技术生成

KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记7 - STM32的CAN学习与测试2 - 双机通讯的发送测试

一、前文回顾

根据《KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记6 - STM32的CAN学习与测试1》的讨论,我实现了单机的回环模式的CAN测试。后来在测试中又有下面的积累。

  1. 在回环模式下,不会有ACK检定,也不会有ACK不应答的报警。 由于CANTX实际上并不把数据发给CAN收发器,只是在芯片里面转一圈就到了CANRX。根据手册的说明,这个过程中是不会有ACK检定。所以不会在CAN_ESR中有ACK ERROR(LEC为3)的指示。参考手册《RM0090 Reference manual - STM32F405/415, STM32F407/417, STM32F427/437 and STM32F429/439 advanced Arm®-based 32-bit MCUs》1082页的说明。

在这里插入图片描述

  1. 可以通过CAN_MCR的第4位NART位和CAN_TSR的ABRQx位来中止当前的发送请求。 如果在DEBUG模式中不小心产生了Transmission错误,比如关掉了回环模式并直接去发送数据。在示波器上会看到数据不停的发送,并且相关的CAN_ESR中有错误指示。这个时候复位CAN_TIxR的TXRQ位是复不了位的。必须通过置位CAN_TSR的ABRQx位来中止掉当前的发送。究其原因,是因为默认的情况下,CAN_MCR的第4位NART位是0,意思是开启自动重新发送。所以一旦检测到错误,CAN外设就会一直尝试发送。有人认为这个最好还是关了。但是笔者目前没有偏好。

二、 双机通讯的发送测试

2.1 一个注意事项

说起这个测试,笔者犯了一个小失误。那就是在debug之前要记得检查一下板子上的BOOT0和BOOT1口的电平是否是正确的。参考手册的第69页的表2。

在这里插入图片描述

这里,如果要从Flash启动,BOOT0端一定要确认接地,悬空可能会导致歧义。DEBUG的时候也许一切正常,一旦脱机使用,就发现程序不能用了。所以要用跳线帽把BOOT0都和GND连好。双机或者多机通讯的时候板子比较多,很有可能会出现这种失误。我的接线如下所示。

在这里插入图片描述

2.2 测试环境

测试用到的开发板、相关的软件和设备如下表所示。

名称型号
开发板HX32F4开发板2块
示波器鼎阳SDS3104X HD
IDEKeil 5

2.3 测试代码

和上一期的代码很相似,只是我们这次不用进入回环模式了。所有的代码如下所示

	get peripherials.s
rRCC	rn 	r8
rGPIOB	rn 	r9
rCAN1	rn	r10

	import SystemCoreClockUpdate
	
	area text, code	
	align 4
	preserve8 
init	proc
	push {r4 - r11, lr}
	
	; Enable the clocks. 
	; APB1 for CAN1, AHB1 for GPIOB
	ldr rRCC, =RCC_BaseAddr
	ldr  r4, [rRCC, #RCC_AHB1ENR]
	orr  r4, #RCC_AHB1ENR_GPIOBEN
	str  r4, [rRCC, #RCC_AHB1ENR]
	ldr  r4, [rRCC, #RCC_APB1ENR]
	orr  r4, #RCC_APB1ENR_CAN1EN
	str  r4, [rRCC, #RCC_APB1ENR]
	
	; Configure the pins for CAN1
	; CAN_TX: PB8, AF9
	; CAN_RX: PB9, AF9
	ldr  rGPIOB, =GPIOB_BaseAddr
	ldr  r4, [rGPIOB, #GPIOx_MODER]
	bfc  r4, #16, #4
	orr  r4, #(GPIOx_MODER_AFIO:shl:16):or:(GPIOx_MODER_AFIO:shl:18)
	str  r4, [rGPIOB, #GPIOx_MODER]
	ldr  r4, [rGPIOB, #GPIOx_OSPEEDR]
	bfc  r4, #16, #4
	orr  r4, #(GPIOx_OSPEEDR_VERYHIGH:shl:16):or:(GPIOx_OSPEEDR_VERYHIGH:shl:18)
	str  r4, [rGPIOB, #GPIOx_OSPEEDR]
	ldr  r4, [rGPIOB, #GPIOx_PUPDR]
	bfc  r4, #16, #4
	orr  r4, #(GPIOx_PUPDR_PU:shl:16):or:(GPIOx_PUPDR_PU:shl:18)
	str  r4, [rGPIOB, #GPIOx_PUPDR]
	ldr  r4, [rGPIOB, #GPIOx_AFRH]
	bfc  r4, #0, #4
	orr  r4, #(9:shl:0) :or: (9:shl:4)
	str	 r4, [rGPIOB, #GPIOx_AFRH]
	
	; Setup the CAN1
	ldr rCAN1, =CAN1_BaseAddr
	
	; Trans to Initialisation Mode
	ldr  r4, [rCAN1, #CAN_MCR]
	bic  r4, #CAN_MCR_SLEEP
	orr	 r4, #CAN_MCR_INRQ
	str	 r4, [rCAN1, #CAN_MCR]
	
	; Set the Baudrate
	; CAN1 is at APB1. 
	push {r0}
	ldr  r4, =SystemCoreClockUpdate
	blx  r4
	lsr  r4, r0, #2
	; Now f_apb1 is r4.
	pop  {r1}
	
	; TS1 and TS2 are 3, BRP + 1 is r4.
	; Enable the loop-back mode
	udiv r4, r4, r1
	mov  r5, #9
	udiv r4, r4 ,r5
	sub  r4, #1
	mov  r5, #3
	ldr  r6, [rCAN1, #CAN_BTR]
	bfc  r6, #16, #6
	bfi	 r6, r4, #0, #10
	bfi	 r6, r5, #16, #4
	bfi	 r6, r5, #20, #3
	str  r6, [rCAN1, #CAN_BTR]
	
	; Set the filter
	ldr  r4, [rCAN1, #CAN_FM1R]
	orr	 r4, #1:shl:0
	str  r4, [rCAN1, #CAN_FM1R]
	
	; The filtered STID is 11, data frame
	; Enable the filter F0R1
	mov  r4, #11:shl:21
	str  r4, [rCAN1, #CAN_F0R1]
	ldr  r4, [rCAN1, #CAN_FA1R]
	orr  r4, #1:shl:0
	str  r4, [rCAN1, #CAN_FA1R]
	ldr  r4, [rCAN1, #CAN_FMR]
	bic  r4, #1:shl:0
	str  r4, [rCAN1, #CAN_FMR]
	
	; Switch CAN1 Peripherial from Initialisation to Normal State
	ldr  r4, [rCAN1, #CAN_MCR]
	bic  r4, #1:shl:0
	str  r4, [rCAN1, #CAN_MCR]
	
	
	; Make a test
	ldr  r4, =Test_String
	ldr  r4, [r4]
	str  r4, [rCAN1, #CAN_TDL0R]
	mov  r4, #4
	ldr  r5, [rCAN1, #CAN_TDT0R]
	bfi  r5, r4, #0, #3
	str  r5, [rCAN1, #CAN_TDT0R]
	ldr  r4, [rCAN1, #CAN_TI0R]
	
	mov  r4, #11:shl:21
	str  r4, [rCAN1, #CAN_TI0R]
	
	
	pop	 {r4 - r11, lr}
	bx	 lr
	
Test_String	dcb	"Andy"	
	endp
	align 4	
can1 dcd	init
	export can1	
		
	end

关于这段代码就没有什么好讲的了。因为每一部分的功能都在上一期讲到了。

有人可能会认为,我应该把尽可能多的常数定义成符号(注意,C语言里面的宏和汇编中的符号不是一回事。符号是在编译和链接过程中都有效的;而宏只要过了预编译就不存在了)。比如,用把1:shl:0定义成CAN_MCR_INRQ。这样会显得专业一点。我非常同意您的看法。我会在后面的版本中改正。

编译,链接。分别下载两块开发板。只不过在第二块开发板上点debug进去。

三、测试结果

还是那个熟悉的调试界面。还是点击TI0R的TXRQ,我们通过0号邮箱发送一个数据帧出去。
在这里插入图片描述

暂时先不去看接收那边。用示波器直接看波形分析。

在这里插入图片描述
根据CAN的协议,ACK那个位必须是总线系统中其他的设备来填。不可以你自己发包自己填ACK。那么从这个波形分析中可以看到一个完整的数据帧了。

关于上一期说到的那个这个示波器的协议解析选件的BUG,在没有ACK应答的时候确实会出现不好确认ACK ERROR的问题。但是在ACK应答正常的情况下,SDS3104X HD是不出这个BUG的。

四、结论和下一步工作

通过上面的讨论可以看出,每一块开发板都可以通过CAN总线在这样一个多主系统中发出邮件。下一步需要做一套收发程序,或者通过两个电脑开DEBUG的方法测试接收的情况。

  • 25
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值