串行外设接口(spi)是一种同步串行数据通信接口,常用于 mcu 与外部设备之间进行同步串行通信。spi是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为pcb的布局上节省空间。cw32l083 内部集成 2 个串行外设 spi 接口,支持双向全双工、单线半双工和单工通信模式,可配置 mcu 作为 主机或从机,支持多主机通信模式,支持直接内存访问(dma)。
单工通信模式
spi 支持单工通信模式,主机和从机通过一根单向数据线进行单发或单收通信。主机使用 mosi 信号线进行单发通信,使用 miso 信号线进行单收通信;从机使用 mosi 信号线进行单收通信, 使用 miso 信号线进行单发通信,未使用的信号线可供其它功能使用。
主机单发,从机单收应用场景下,连接框图如下:
主机单发配置:
设置 spix_cr1.mode 为 0x1,spi 工作于单工单发通信模式;
设置 spix_cr1.mstr 为 1,spi 工作于主机模式。
设置 spix_ssi.ssi 为 0,在从机选择 cs 引脚输出低电平,作为通信起始信号。
当发送缓冲器为空时,即 spix_isr.txe 标志位为 1,将待发送的一帧数据写入 spix_dr 寄存器,数据在同步移位时钟信号的控制下从 mosi 引脚输出。
当写入最后一帧数据后,必须等待发送缓冲空标志位 spix_isr.txe 变为 1,同时 spi 总线忙标志位 spix_isr. busy 变为 0,以确保数据发送完毕。然后设置 spix_ssi.ssi 为 1,使从机选择 cs 引脚输出高电平,结束本次通信。
从机单收配置:
设置 spix_cr1.mode 为 0x2,spi 工作于单工单收通信模式;
设置 spix_cr1.mstr 为 0,spi 工作于从机模式。
当检测到 cs 引脚变为低电平时,从机开始与主机通信。当接收缓冲器非空时,即 spix_isr.rxne 标志位为 1,表示已经接收完成一帧数据,此时可以读取 spix_dr 寄存器。当检测到 cs 引脚变为高电平时,本次通信结束。
主机单收,从机单发应用场景下,连接框图如下:
具体设置与主机单发和从机单收类似,详情可查看用户手册。
spi中断
spi 控制器支持 8 个中断源,当 spi 中断触发事件发生时,中断标志位会被硬件置位,如果设置了对应的中断使能控制位,将产生中断请求。
在用户 spi 中断服务程序中,应查询相关 spi 中断标志位,以进行相应的处理,在退出中断服务程序之前,要清除该中断标志位,避免重复进入中断程序。
实例演示: spi单工模式进行主从机通信,主机单发,从机单收。
spiy(主机)采用中断方式发送txbuffer缓冲区中的数据,spiz(从机)采用中断方式接收数据并存储到rxbuffer缓冲区,比较txbuffer和rxbuffer,如果数据一致led1亮,否则led2亮。
1. 配置rcc
void rcc_configuration(void){ rcc_hsi_enable(rcc_hsiosc_div2); //sysclk = hsi = 24mhz = hclk = pclk rcc_ahbperiphclk_enable(spiy_gpio_clk | spiz_gpio_clk | rcc_ahb_periph_gpioc, enable); //外设时钟使能 spiy_apbclkenx(spiy_clk, enable); spiz_apbclkenx(spiz_clk, enable);}
2. 配置gpio
void gpio_configuration(void){ gpio_inittypedef gpio_initstructure = {0}; spiy_af_sck; //spi sck mosi 复用 spiy_af_mosi; spiz_af_sck; spiz_af_mosi; gpio_initstructure.pins = spiy_sck_pin; //推挽输出 gpio_initstructure.mode = gpio_mode_output_pp; gpio_init(spiy_gpio, gpio_initstructure); gpio_initstructure.pins = spiy_mosi_pin; gpio_init(spiy_gpio, gpio_initstructure); gpio_initstructure.pins = spiz_sck_pin; //浮空输入 gpio_initstructure.mode = gpio_mode_input; gpio_init(spiz_gpio, gpio_initstructure); gpio_initstructure.pins = spiz_mosi_pin; gpio_init(spiz_gpio, gpio_initstructure); gpio_initstructure.pins = gpio_pin_3 | gpio_pin_2; //pc3 led1 / pc2 led2 gpio_initstructure.mode = gpio_mode_output_pp; gpio_init(cw_gpioc, gpio_initstructure); pc03_setlow();//led灭 pc02_setlow();}
3. 配置spi
void spi_configuration(){ spi_inittypedef spi_initstructure = {0}; spi_initstructure.spi_direction = spi_direction_1line_txonly; // 单工单发 spi_initstructure.spi_mode = spi_mode_master; // 主机模式 spi_initstructure.spi_datasize = spi_datasize_8b; // 帧数据长度为8bit spi_initstructure.spi_cpol = spi_cpol_low; // 时钟空闲电平为低 spi_initstructure.spi_cpha = spi_cpha_1edge; // 第一个边沿采样 spi_initstructure.spi_nss = spi_nss_soft; // 片选信号由ssi寄存器控制 spi_initstructure.spi_baudrateprescaler = spi_baudrateprescaler_8; // 波特率为pclk的8分频 spi_initstructure.spi_firstbit = spi_firstbit_msb; // 最高有效位 msb 收发在前 spi_initstructure.spi_speed = spi_speed_low; // 低速spi spi_init(spiy, spi_initstructure); spi_initstructure.spi_direction = spi_direction_1line_rxonly; // 单工单收 spi_initstructure.spi_mode = spi_mode_slave; // 从机模式 spi_init(spiz, spi_initstructure); spi_cmd(spiy, enable); spi_cmd(spiz, enable);}
4. 配置nvic中断函数
void nvic_configuration(void){ nvic_setpriority(spiy_irq, 1); //优先级,无优先级分组 nvic_setpriority(spiz_irq, 0); nvic_enableirq(spiy_irq); //spi中断使能 nvic_enableirq(spiz_irq);}void spi1_irqhandler(void)//spi1中断函数{ if(spi_getitstatus(cw_spi1, spi_it_txe) != reset) { if(txcounter == buffersize - 1) { spi_itconfig(cw_spi1, spi_it_txe, disable); } spi_senddata(cw_spi1, txbuffer[txcounter++]); }}void spi2_irqhandler(void) //spi2中断函数{ if(spi_getitstatus(cw_spi2, spi_it_rxne) != reset) { rxbuffer[rxcounter++] = spi_receivedata(cw_spi2); }}
5. 比较两个buffers区
teststatus buffercmp(uint8_t* pbuffer1, uint8_t* pbuffer2, uint16_t bufferlength){ while(bufferlength--) { if(*pbuffer1 != *pbuffer2) { return failed; } pbuffer1++; pbuffer2++; } return passed;}
6. 主程序
int32_t main(void){ rcc_configuration();//配置rcc gpio_configuration();//配置gpio spi_configuration();//配置spi nvic_configuration();//配置nvic spi_itconfig(spiz, spi_it_rxne, enable); //使能 spiz rxne 中断 spi_nssinternalsoftwareconfig(spiz, spi_nssinternalsoft_reset); //软件nss,选中spiz spi_itconfig(spiy, spi_it_txe, enable); //使能 spiy txe 中断 while(rxcounter < buffersize); //等待收发完成 spi_nssinternalsoftwareconfig(spiz, spi_nssinternalsoft_set); //释放spiz transferstatus = buffercmp(txbuffer, rxbuffer, buffersize); //检查收发数据一致性 if(transferstatus == passed) //passed { pc03_sethigh();//led1亮 } else //failed { pc02_sethigh();//led2亮 } while(1) { }}
7.实验结果显示:led1亮起,buffers区数据相等,spi单工模式主从通讯(中断方式)功能实现。
来源:武汉芯源半导体
免责声明:本文为转载文章,转载此文目的在于传递更多信息,版权归原作者所有。本文所用视频、图片、文字如涉及作品版权问题,请联系小编进行处理
BinaryTree Power365 Directory Sync具有哪些功能呢
开关电源中如何选择合适的电感
人工智能芯片竞争升级,nVidia较英特尔更有优势
智己汽车携手宁德时代共同开发“掺硅补锂电芯”技术
什么是SLAM技术?SLAM技术的工作原理
CW32的SPI单工模式主从通信介绍
Vishay发布6款低输入电流光耦VO617A
Vega和Ryzen在手 AMD能否重新崛起?
Epiq扩大计划范围 彻底实现人工智能的应用
嵌入式视觉处理器让神经网络性能翻倍
魅族16th搭载骁龙845移动平台,采用AI双摄,可让拍照体验更加出色
Vishay推出基于PLCC-2和超小尺寸MiniLED封装的新款汽车级电源指示LED
最新M471K系列单片机开发板测试
浅析软包电池优缺点及锂电池模组的压力
科创板澜起科技董事Brent Alexander Young介绍、履历信息
扩展MAX9930在CATV应用的功能
方方面面话笔记本电池(二)
Luminar考虑在亚洲新建激光雷达工厂
智能镜子震撼来袭,将为你打造专属你的智慧家庭
【节能学院】浅谈安科瑞能源管控平台在碳达峰行动中的应用