【一兮】nrf52840的SPI一主多从,关于CS片选自动选中的解决方法

在尝试使用nrf52840进行一主多从SPI通信时,遇到硬件SPI自动选中某一从设备的问题。初始尝试通过MCUIO控制片选信号失败。最终解决方案是每次通信前重新初始化硬件SPI,配置相应的CS引脚,通信完成后进行反初始化,以切换到其他从设备。这种方法虽消耗一定MCU资源,但对整体影响微小。

1.问题背景

答:笔者需要用nrf52840的SPI进行一主多从的SPI通信,主机用nrf52840,通过片选选中从芯片通过SPI进行通信,开始我的想法是,就简单的MCU IO输出高低电平控制CS的高低,加在SPI发送函数前面便能实现自己想要的效果。发现并没有解决问题,在多次验证的时候发现nrf52840的硬件SPI的初始化我即使不配置CS引脚,通信的时候CS也会自动选中其中的一片,其中一片pin为0 0,另一片pin为 0 8,每次默认选中的都是pin 0 0。

2.解决方案

答:简单的在SPI的发送函数前面加入CS IO口输出电平无法选中,那么换一个思路。每次在SPI发送函数的前面都进行一次初始化硬件SPI,这里的初始化硬件SPI配置相应的CS引脚即可,虽然初始化耗费了MCU资源,但是这点资源对于MCU来说凤毛麟角。初始化完一个对于的CS脚硬件SPI的时候,发送完毕,应当使用下面的反初始化函数执行后。例如下次选中pin0 8的cs,再用下面的初始化函数初始化,下一个要发送给另一片,例如pin 0 0的cs,反初始化后再进行。以此类推,笔者使用的是SPI3

nrfx_err_t nrfx_spim_init(nrfx_spim_t  const * const p_instance,
                          nrfx_spim_config_t const * p_config,
                          nrfx_spim_evt_handler_t    handler,
                          void                     * p_context)



void nrfx_spim_uninit(nrfx_spim_t const * const p_instance)

所给引用中未提及STM33在SPI通信中从的相关内容,无法根据引用准确回答STM33 SPI从的实现方法和配置。不过在STM系列芯通用的SPI通信从场景中,般实现方法和配置思路如下: ### 实现方法SPI从系统里,设备通过信号(CS)来择与哪个从设备进行通信。设备的SPI接口产生时钟信号(SCK)和数据信号(MOSI、MISO),每个从设备都有独立的引脚,当设备需要和某个从设备通信时,将对应的引脚拉低,选中该从设备进行数据传输。 ### 配置 1. **SPI控制器配置**:对设备和从设备的SPI控制器进行初始化,设置通信参数,像时钟极性(CPOL)、时钟相位(CPHA)、数据位长度、波特率等。例如在STM32中,可使用HAL库函数`HAL_SPI_Init`来初始化SPI控制器。 ```c SPI_HandleTypeDef hspi; void MX_SPI_Init(void) { hspi.Instance = SPIx; // SPI外设实例 hspi.Init.Mode = SPI_MODE_MASTER; // 模式 hspi.Init.Direction = SPI_DIRECTION_2LINES; // 双线全双工 hspi.Init.DataSize = SPI_DATASIZE_8BIT; // 数据位长度 hspi.Init.CLKPolarity = SPI_POLARITY_LOW; // 时钟极性 hspi.Init.CLKPhase = SPI_PHASE_1EDGE; // 时钟相位 hspi.Init.NSS = SPI_NSS_SOFT; // 软件 hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; // 波特率预分频 hspi.Init.FirstBit = SPI_FIRSTBIT_MSB; // 高位先行 hspi.Init.TIMode = SPI_TIMODE_DISABLE; // 不使用TI模式 hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; // 不使用CRC hspi.Init.CRCPolynomial = 7; // CRC项式 if (HAL_SPI_Init(&hspi) != HAL_OK) { Error_Handler(); } } ``` 2. **引脚配置**:将每个从设备的引脚配置为普通GPIO输出模式。在和某个从设备通信时,把对应的引脚拉低,通信结束后再拉高。 ```c // 假设CS引脚为GPIOA_PIN_0 GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_0; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 选中从设备 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 通信结束,取消选中 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); ``` ### 使用注意事项 - 信号的控制要准确,防止个从设备同时被选中,从而引发通信冲突。 - 确保设备和从设备的SPI通信参数配置致,不然会导致数据传输错误。 - 要考虑SPI总线的负载能力,若连接的从设备过,可能会影响通信的稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值