[导读] 大家好,我是逸珺。
之前用stm32的spi需要控制很多外部芯片,可是一个spi的外设只有一个片选,要实现独立片选一主多从,怎么实现呢?
spi总线拓扑一般地,spi总线按照下图方式进行连接,一主多从。
如上图:
每个从设备都有独立的片选引脚,主机同一时间段内,与一个从设备进行通信,也即选中一个从设备。mosi/miso/sclk并联在一起miso须是三态门,当从设备未选中时,该脚须设置为高阻态,而不能是输出态,否则会影响总线 !对于mosi/sclk,虽然并联在一起,但是由于仅一个输出,多输入。但是你看stm32的spi外设,一个spi仅有一个nss信号,以stm32f407的spi2为例:
那么要实现前面说的一主多从,怎么办呢?有朋友说,直接用gpio去模拟不就可以了。
不错,spi总线要用gpio模拟还是很容易的,但是这样做波特率做不高,需要占用cpu时间,效率比较低!而用spi外设控制器,底层bit流的收发由外设控制器实现,用gpio模拟则需要cpu参与。
怎么破呢?菊花链拓扑
这种方案,省引脚。但是要移位控制,相对独立片选效率还是低不少。
独立片选拓扑spi外设的mosi、miso、sck还是照用不误,但是片选我们不用,设置成通用输出模式,再用其他的gpio片选从芯片即可。
上代码看看:
void hal_spi_mspinit(spi_handletypedef* hspi){ gpio_inittypedef gpio_initstruct = {0}; if(hspi->instance==spi1) { __hal_rcc_spi1_clk_enable(); __hal_rcc_gpioa_clk_enable(); /**spi1 gpio configuration pa5 ------> spi1_sck pa6 ------> spi1_miso pa7 ------> spi1_mosi pa15 ------> spi1_nss 但是这里不用 */ gpio_initstruct.pin = gpio_pin_5|gpio_pin_6|gpio_pin_7; gpio_initstruct.mode = gpio_mode_af_pp; gpio_initstruct.pull = gpio_nopull; gpio_initstruct.speed = gpio_speed_freq_very_high; gpio_initstruct.alternate = gpio_af5_spi1; hal_gpio_init(gpioa, &gpio_initstruct); /*__hal_rcc_gpioc_clk_enable(); gpio_initstruct.pin = gpio_pin_1; gpio_initstruct.mode = gpio_mode_af_pp; gpio_initstruct.pull = gpio_nopull; gpio_initstruct.speed = gpio_speed_freq_very_high; gpio_initstruct.alternate = gpio_af5_spi1; hal_gpio_init(gpioc, &gpio_initstruct);*/ }}初始化spi外设
#define spi_cs1 gpio_pin_1#define spi_cs1_port gpioc#define spi_cs2 gpio_pin_2#define spi_cs2_port gpioc#define spi_cs3 gpio_pin_3#define spi_cs3_port gpiocstatic void init_spi(spi_handletypedef * spi_handle){ /* spi1 parameter configuration*/ spi_handle->instance = spi1; spi_handle->init.mode = spi_mode_master; spi_handle->init.direction = spi_direction_2lines; spi_handle->init.datasize = spi_datasize_8bit; spi_handle->init.clkpolarity = spi_polarity_low; spi_handle->init.clkphase = spi_phase_1edge; spi_handle->init.nss = spi_nss_hard_output; spi_handle->init.baudrateprescaler = spi_baudrateprescaler_4; spi_handle->init.firstbit = spi_firstbit_msb; spi_handle->init.timode = spi_timode_disable; spi_handle->init.crccalculation = spi_crccalculation_disable; spi_handle->init.crcpolynomial = 10; assert (hal_spi_init(spi_handle) != hal_ok); gpio_inittypedef gpio_initstructure; __hal_rcc_gpioc_clk_enable(); gpio_initstructure.pin = spi_cs1; gpio_initstructure.mode = gpio_mode_output_pp; gpio_initstructure.pull = gpio_nopull; gpio_initstructure.speed = gpio_speed_freq_medium; hal_gpio_init(spi_cs1_port, &gpio_initstructure); gpio_initstructure.pin = spi_cs2; hal_gpio_init(spi_cs2_port, &gpio_initstructure); gpio_initstructure.pin = spi_cs3; hal_gpio_init(spi_cs3_port, &gpio_initstructure); }从而原来spi的收发函数前后加上片选信号即可:
typedef enum { spi_ch_1=0, spi_ch_2, spi_ch_3, spi_ch_last,} spi_ch;static hal_statustypedef spi_select(spi_ch ch){ switch (ch) { case spi_ch_1: hal_gpio_writepin(spi_cs1_port,spi_cs1,gpio_pin_reset); break; case spi_ch_2: hal_gpio_writepin(spi_cs2_port,spi_cs2,gpio_pin_reset); break; case spi_ch_3: hal_gpio_writepin(spi_cs3_port,spi_cs3,gpio_pin_reset); break; default: return hal_error; } return hal_ok;}static hal_statustypedef spi_deselect(spi_ch ch){ switch (ch) { case spi_ch_1: hal_gpio_writepin(spi_cs1_port,spi_cs1,gpio_pin_set); break; case spi_ch_2: hal_gpio_writepin(spi_cs2_port,spi_cs2,gpio_pin_set); break; case spi_ch_3: hal_gpio_writepin(spi_cs3_port,spi_cs3,gpio_pin_set); break; default: return hal_error; } return hal_ok;}hal_statustypedef spi_transmitreceive(spi_ch ch, spi_handletypedef *hspi, uint8_t *ptxdata, uint8_t *prxdata, uint16_t size, uint32_t timeout){ hal_statustypedef ret; if(ch>=spi_ch_last) return hal_error; spi_select(ch); ret = hal_spi_transmitreceive(hspi,ptxdata,prxdata,size,timeout); spi_deselect(ch); return ret;}hal_statustypedef spi_transmit(spi_ch ch, spi_handletypedef *hspi, uint8_t *pdata, uint16_t size, uint32_t timeout){ hal_statustypedef ret; if(ch>=spi_ch_last) return hal_error; spi_select(ch); ret = hal_spi_transmit(hspi,pdata,size,timeout); spi_deselect(ch); return ret; }如此一来,一个spi外设就可以控制多个从芯片了。你如果有兴趣,不妨照这个思路试试看。
2019世界机器人大会,4大看点抢先看
支付宝大战ApplePay 移动支付市场火药味十足
固态电容的好处
PowerVR Serise9XE和9XM是什么?更适用于嵌入式平台的旗舰GPU
三轴全自动转轴磨合机PS-2503T的结构
如何实现独立片选一主多从
比特币存在法律风险,国内平台关停进入倒计时
华为公开芯片新专利,不再被卡脖子
汽车前照系统与LED自适应前照系统探讨
快速掌握MIPI开发攻略,对接百度人工智能计算卡EdgeBoard
为大家简单介绍关于小间距LED显示屏的性能特征
锂电子电池技术快速发展
点光源为源自半导体激光的白色LED光源
微软Office 2013汉化版网上曝光
全志科技在智能驾舱领域技术实力被认可
数字化转型的最好方式到底是什么
小米主导了可穿戴设备市场,苹果位居第二
!吉时利2303/吉时利2303/吉时利2303!小兵/李S
空压机物联网在线监控节能平台的系统架构及功能介绍
倪光南表示,中兴事件后,国产自主芯片的研发必将上一个新的台阶