STM32 SPI读DW1000的Device_ID的问题与解决


官方Demo API读出的值为0,HAL读出的值为{0x 一串数字}
问题的解决方法,简单说就是增加唤醒的时长,暂时是这样解决的,不一定有用
还有一点,所有VCC和GND引脚应该都接上

硬件

  • STM32F103ZET
  • DWM1000
  • CH340

引脚和配置

STM32DW1000
PA0RSTN
PA4(SPI1_NSS)CSN
PA5(SPI1_SCK)CLK
PA6(SPI_MISO)MISO
PA7(SPI1_MOSI)MOSI
PB5IRQN
PB0WUP
GNDGND

问题的经过

  1. 将官方的Demo(https://www.decawave.com/wp-content/uploads/2019/01/dw1000_api_rev2p14.zip)移植到了CubeMX创建的Keil5 MDK项目后(已移除了LCD、LED和USB部分),但当我想调用官方的dwt_readdevid()函数读取Device时,读出来的值为0。
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_USART1_UART_Init();
  uint8 buf[20];
  // wakeup and init 
  dwt_spicswakeup(buf, 20);
  reset_DW1000(); /* Target specific drive of RSTn line into DW1000 low for a period. */
  port_set_dw1000_slowrate();
  uint32 dwt_ID = 0;
  // dwt_readdevid()是官方的函数,读写寄存器0x00,理论上应该读出来的是0xDECA0130
  dwt_ID = dwt_readdevid();
  // 可惜读出来的值为0
  printf("ID:%lx\r\n",dwt_ID);

在这里插入图片描述
3. 然后,我再看了网络中大部分类似该篇https://mculover666.blog.csdn.net/article/details/114890352 的文章(这是直接使用HAL库),读出来的值为0x 800210a,可这也是不正确的。在看了https://decaforum.decawave.com/search?q=device%20id 论坛中相关话题,也没有找到合适的答案。而根据这份文档的https://www.decawave.com/sites/default/files/aps022_debugging_dw1000_based_products_systems.pdf的第7页,读出类似的值说明SPI的配置有问题

If the device returns some other value e.g. 0xBD940260: -

  • the SPI mode is probably not set correctly (the controller’s SPI mode does not match the DW1000 SPI mode); or
  • the data read back is shifted. Check the controller’s SPI configuration.

在这里插入图片描述

  1. 我又按照上述文档的如下方式,再尝试读写0x21寄存器,写入0x03,但读出还是0
	// Nss
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
	uint8 dataA[20] = { 0x03 };
	uint8 dataB[20];
    // 这是官方读取设备函数(寄存器ID,index,长度,buffer)
	dwt_writetodevice(0x21, 0, 20, &dataA[0]);
	dwt_readfromdevice(0x21, 0 , 20, &dataB[0]);
	printf("(api reg 0x21)the data a is 0x%d, datab is 0x%d\r\n", dataA[0], dataB[0]);

在这里插入图片描述

deca_reg.h对0x21的描述为用户指定的SFD序列

/****************************************************************************//**
 * @brief Bit definitions for register USR_SFD
 *        Please read User Manual : User defined SFD sequence
**/
#define USR_SFD_ID              0x21            /* User-specified short/long TX/RX SFD sequences */
  1. 但疑惑的是,我用HAL库的这个HAL_SPI_TransmitReceive函数读写时,写入0x04,读出0x04,时而为0x0。
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
	uint8 dataA[20] = { 0x03, 0x04 };
	uint8 dataB[20];
	printf("***********\r\n");
	HAL_SPI_TransmitReceive(&hspi1, &dataA[1], &dataB[1], 4, HAL_MAX_DELAY);

问题的矛头

  • 移植出的问题。
文件函数修改后说明
deca_spi.creadfromspiint readfromspi(uint16 headerLength,const uint8 *headerBuffer, uint32 readlength, uint8 *readBuffer){与deca_device_api.h文件保持一致
deca_spi.creadfromspiHAL_SPI_Transmit(&hspi1, (uint8 *)&headerBuffer[i], 1, HAL_MAX_DELAY);
deca_spi.cwritetospiint writetospi(uint16 headerLength,const uint8 *headerBuffer,uint32 bodyLength,const uint8 *bodyBuffer){
port.hport_deca_isr_t port_deca_isr;extern port_deca_isr_t port_deca_isr;
port.h末尾在这里插入图片描述为port.c的延时函数int usleep(useconds_t usec)定义类型useconds_t ,原是STM32Workspace软件插件中type.h封装的
port.cportGetTickCnt__INLINE uint32_t portGetTickCnt(void)

在port.h、port.c文件中需要对USB、LCD等相关代码清除,引入main.h声明引脚

  • SPI配置的问题,对比官方Demo中的CubeMX项目具体配置(时钟输入不必为12,串口打印会乱码)。

这是串口打印出来的结果
在这里插入图片描述

问题的解决

根据https://decaforum.decawave.com/uploads/short-url/jQPkxawHn3LzbJln0QqjPShspZP.pdf文档第48页,dwt_spicswakeup函数唤醒DW1000至少需要500us,并取决于SPI读写速率
在这里插入图片描述那么在deca_device.c文件下的dwt_spicswakeup函数中如下修改

int dwt_spicswakeup(uint8 *buff, uint16 length)
{
    if(dwt_readdevid() != DWT_DEVICE_ID) // Device was in deep sleep (the first read fails)
    {
        // Need to keep chip select line low for at least 500us
        dwt_readfromdevice(0x0, 0x0, length, buff); // Do a long read to wake up the chip (hold the chip select low)

        // Need 5ms for XTAL to start and stabilise (could wait for PLL lock IRQ status bit !!!)
        // NOTE: Polling of the STATUS register is not possible unless frequency is < 3MHz
        deca_sleep(5);
    }
    else
    {
			//printf("0x%lx", dwt_readdevid());
        return DWT_SUCCESS;
    }
    // DEBUG - check if still in sleep mode
    if(dwt_readdevid() != DWT_DEVICE_ID)
    {
			deca_sleep(200);//这里加长延时,值自行调整
        return DWT_ERROR;
    }
		printf("0x%lx", dwt_readdevid());
    return DWT_SUCCESS;
}

在main.c文件main函数测试

printf("DW1000:\r\n");
while (dwt_spicswakeup(dummy_buffer, DUMMY_BUFFER_LEN) != DWT_SUCCESS);

串口输出结果
在这里插入图片描述其它相应配置
在这里插入图片描述

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值