STM32硬件SPI怎么判断数据发完了,是哪个标志位

STM32硬件SPI怎么判断数据发完了,是哪个标志位,第1张

SPI_I2S_FLAG_TXE: Transmit buffer empty flag

SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)

检测事件标识位 发送完成

SPI_I2S_IT_TXE: Transmit buffer empty interrupt

SPI_I2S_GetITStatus(SPI1,SPI_I2S_IT_TXE )

开启了中断之后 检测中断标识位 发送完成

ESP32 芯片包含两个硬件定时器组。每组有两个通用硬件定时器。它们都是基于 16 位预分频器和 64 位自动重载功能的向上/向下计数器的 64 位通用定时器。

hw_timer_t timerBegin(uint8_t num, uint16_t divider, bool countUp){}

参数:

返回值:

返回一个计时器结构体指针 hw_timer_t ,我们预定义一个指针接收他

void timerEnd(hw_timer_t timer)

参数:

void timerAttachInterrupt(hw_timer_t timer, void ( fn)(void), bool edge){}

参数:

void timerDetachInterrupt(hw_timer_t timer)

void timerAlarmWrite(hw_timer_t timer, uint64_t alarm_value, bool autoreload){}

参数:

void timerAlarmEnable(hw_timer_t timer){}

参数:

void timerAlarmDisable(hw_timer_t timer)

bool timerAlarmEnabled(hw_timer_t timer)

ESP32有两个I2C控制器(也称为端口),负责处理两条I2C总线上的通信。每个I2C控制器都可以作为主机或从机运行。引脚21 默认的SDA, 引脚22是默认的SCL

IIC需要引入自带库 Wireh Wire继承steam类 steam类有的他都有

void requestFrom(uint16_t address, uint8_t size, bool sendStop)

请求完成后 主机可以用 Wireavailable() 和 Wireread() 等函数等待并获取从机的回答

参数:

void beginTransmission(int address)

随后, 主机可以使用 Wirewrite(); 写数据并使用 WireendTransmission(); 结束传输

参数:

结束传输, 并释放IIC

返回值: uint8_t 类型

当作为主机时: 主机将要发送的数据加入发送队列;

当作为从机时: 从机发送的数据给主机;

参数:

返回值: byte类型

输入的字节数

返回接收到的字节数

返回值: byte类型

当作为主机时: 主机使用requestFrom()后 要使用此函数获取数据;

当作为从机时: 从机读取主机给的数据;

返回值: 读到的字节数据 byte

size_t readBytes(char buffer, size_t length)

参数:

返回值: 数据长度

size_t readBytesUntil(char terminator, char buffer, size_t length)

参数:

返回值: 数据长度

Wirebusy();

返回布尔值

继承自steam类, 个人感觉iic不会用到的

parseFloat

parseInt

find

findUntil

setTimeout

这些都是steam继承来的 大家灵活应用

从机有些函数和主机是一样的, 请看上一章节,本章节只有不一样的部分

Wirebegin(adress); //adress取值0~127

void onRequest(void ()())

参数:

void onReceive(void ()(int))

参数:

ESP32有四个SPI外设,分别为SPI0、SPI1、HSPI和VSPI。

SPI通讯流程如下:

SPI接口默认VSPI 接口频率1 000 000, 数据默认采用MSBFIRST(低有效位优先), 时钟模式:SPI_MODE0(SCLK闲置为0, SCLK上升沿采样)

参数:

参数:

参数:

采用该函数,可以代替上面三个函数了

参数:

结束SPI通信

参数:

返回值: 接收到的数据

求SPI的SSD1306在linux下的测试程序理解SPI的驱动框架,还是从最基本的三个入口点触发,platform_device,platform_bus,platform_driver。

其中内核一提供给platform_bus,platform_driver在spi_s3c24xx_gpioc和spi_s3c24xxcc中,其中spi_s3c24xx_gpioc用于IO模拟SPI (本例讨论的是IO模拟SPI),spi_s3c24xxcc用于s3c24xx的硬件SPI。因此,我们需要动手写一个platform_device。

看看spi_s3c24xx_gpioc做了些什么。

static int s3c2410_spigpio_probe(struct platform_device dev)

{

/ [cgw]: 分配一个SPI主机 /

master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio));

sp = spi_master_get_devdata(master);

platform_set_drvdata(dev, sp);

/ [cgw]: 分配与spi硬件相关的配置,如指定哪些IO为MISO,MOSI,SCLK,CS,SPI工作模式,最大时钟等等 /

/ copy in the plkatform data /

sp->info = dev->devplatform_data;

/ [cgw]: 提供实现SPI各种模式的时序的基本方法,和CS的激活方法 /

/ setup spi bitbang adaptor /

sp->bitbangmaster = spi_master_get(master);

sp->bitbangchipselect =

看你用的是那种单片机和温度新片了,我用过Microchip公司的TC77温度芯片,百度上能找到它的资料,用软件模拟SPI通信或直接用硬件SPI通信都可以,我用的是PIC18F4550单片机,用PICC进行编程:

软件SPI通信程序:

#include "C:\sample\spih"

unsigned char rw_spi(unsigned char val)

{unsigned char Bit_counter;

for(Bit_counter=8;Bit_counter!=0;Bit_counter--)

{output_low(pin_b1);

output_low(pin_b0);

if(val&0x80) output_high(pin_b0);

val<<=1;

output_high(pin_b1);

if(input(pin_b0)) val|=1;

}

output_low(pin_b1);

return val;

}

void main()

{

unsigned char value;

setup_adc_ports(NO_ANALOGS|VSS_VDD);

setup_adc(ADC_OFF);

setup_psp(PSP_DISABLED);

setup_spi(SPI_SS_DISABLED);

setup_wdt(WDT_OFF);

setup_timer_0(RTCC_INTERNAL);

setup_timer_1(T1_DISABLED);

setup_timer_2(T2_DISABLED,0,1);

setup_timer_3(T3_DISABLED|T3_DIV_BY_1);

setup_comparator(NC_NC_NC_NC);

setup_vref(FALSE);

//Setup_Oscillator parameter not selected from Intr Oscillator Config tab

// TODO: USER CODE!!

while(1)

{output_high(pin_b2);

output_high(pin_d0);

delay_ms(1000);

output_low(pin_d0);

delay_ms(1000);

output_low(pin_b2);

value=rw_spi(0x00);

putc(value);

value=rw_spi(0x00);

putc(value);

output_high(pin_b2);

delay_ms(10);

output_low(pin_b2);

rw_spi(0x00);

rw_spi(0x00);

}

}

硬件SPI程序:

#include "C:\sample\spifyth"

#int_SSP

#define EEPROM_ADDRESS BYTE

void SSP_isr(void)

{

}

void main(EEPROM_ADDRESS address)

{

int data=0;

setup_adc_ports(NO_ANALOGS|VSS_VDD);

setup_adc(ADC_OFF);

setup_psp(PSP_DISABLED);

setup_spi(SPI_MASTER|SPI_L_TO_H|SPI_CLK_DIV_4);

setup_wdt(WDT_OFF);

setup_timer_0(RTCC_INTERNAL);

setup_timer_1(T1_DISABLED);

setup_timer_2(T2_DISABLED,0,1);

setup_comparator(NC_NC_NC_NC);

setup_vref(FALSE);

enable_interrupts(INT_SSP);

enable_interrupts(GLOBAL);

//Setup_Oscillator parameter not selected from Intr Oscillator Config tab

// TODO: USER CODE!!

while(1){

delay_ms(2000);

output_low(pin_b2);

spi_write(0x9);

spi_write(0x80);

delay_ms(11);

spi_write(0x18);

spi_write(address);

data=spi_read(0);

putc(data);

delay_ms(20);

data=spi_read(0);

putc(data);

delay_ms(100);

output_high(pin_b2);

}

}

希望对你有用。。

本实验采用W25Q64芯片

W25Q64是华邦公司推出的大容量SPI

FLASH产品,其容量为64Mb。该25Q系列的器件在灵活性和性能方面远远超过普通的串行闪存器件。W25Q64将8M字节的容量分为128个块,每个块大小为64K字节,每个块又分为16个扇区,每个扇区4K个字节。W25Q64的最小擦除单位为一个扇区,也就是每次必须擦除4K个字节。所以,这需要给W25Q64开辟一个至少4K的缓存区,这样必须要求芯片有4K以上的SRAM才能有很好的 *** 作。

W25Q64的擦写周期多达10W次,可将数据保存达20年之久,支持27~36V的电压,支持标准的SPI,还支持双输出/四输出的SPI,最大SPI时钟可达80Mhz。

一。SPI接口原理

(一)概述

高速,全双工,同步的通信总线。

全双工:可以同时发送和接收,需要2条引脚

同步: 需要时钟引脚

片选引脚:方便一个SPI接口上可以挂多个设备。

总共四根引脚。

(二)SPI内部结构简明图

MISO: 做主机的时候输入,做从机的时候输出

MOSI:做主机的时候输出,做从机的时候输入

主机和从机都有一个移位寄存器,在同一个时钟的控制下主机的最高位移到从机的最高位,同时从机的最高位往前移一位,移到主机的最低位。在一个时钟的控制下主机和从机进行了一个位的交换,那么在8个时钟的控制下就交换了8位,最后的结果就是两个移位寄存器的数据完全交换。

在8个时钟的控制下,主机和从机的两个字节进行了交换,也就是说主机给从机发送一个字节8个位的同时,从机也给主机传回来了8个位,也就是一个字节。

(三)SPI接口框图

上面左边部分就是在时钟控制下怎么传输数据,右边是控制单元,还包括左下的波特率发生器。

(四)SPI工作原理总结

(五)SPI的特征

(六)从选择(NSS)脚管理

两个SPI通信首先有2个数据线,一个时钟线,还有一个片选线,只有把片选拉低,SPI芯片才工作,片选引脚可以是SPI规定的片选引脚,还可以通过软件的方式选择任意一个IO口作为片选引脚,这样做的好处是:比如一个SPI接口上挂多个设备,比如挂了4个设备,第二个用PA2,第三个用PA3,第四个用PA4作为片选,我们

跟第二个设备进行通信的时候,只需要把第二个片选选中,比如拉低,其他设备的片选都拉高,这样就实现了一个SPI接口可以连接个SPI设备,战舰开发板上就是通过这种方法来实现的。

(七)时钟信号的相位和极性

时钟信号的相位和极性是通过CR寄存器的 CPOL 和 CPHA两个位确定的。

CPOL:时钟极性,设置在没有数据传输时时钟的空闲状态电平。CPOL置0,SCK引脚在空闲时为低电平,CPOL置1,SCK引脚在空闲时保持高电平。

CPHA:时钟相位 设置时钟信号在第几个边沿数据被采集

CPHA=1时:在时钟信号的第二个边沿

CPOL=1,CPHA=1,

CPOL=1表示时钟信号在没有数据传输时即空闲时的状态为高电平。如果CPHA=1,那么数据就在时钟信号的第二个边沿即上升沿的时候被采集。

CPOL= 0,CPHA=1, CPOL=0表示时钟信号在没有数据传输时即空闲时的状态为低电平。

如果CPHA=1,那么数据就在时钟信号的第二个边沿即下降沿的时候被采集。

CPHA=0时:在时钟信号的第一个边沿

CPOL=1,CPHA=0,

CPOL=1表示时钟信号在没有数据传输时即空闲时的状态为高电平。如果CPHA=1,那么数据就在时钟信号的第一个边沿即下降沿的时候被采集。

CPOL= 0,CPHA=0, CPOL=0表示时钟信号在没有数据传输时即空闲时的状态为低电平。

如果CPHA=1,那么数据就在时钟信号的第一个边沿即上升沿的时候被采集。

为什么要配置这两个参数

因为SPI外设的从机的时钟相位和极性都是有严格要求的。所以我们要根据选择的外设的时钟相位和极性来配置主机的相位和极性。必须要与从机匹配。

(八)数据帧的格式和状态标志

数据帧格式:根据CR1寄存器的LSBFIRST位的设置,数据可以MSB在前也可以LSB在前。

根据CR1寄存器的DEF位,每个数据帧可以是8位或16位。

(九)SPI中断

(十)SPI引脚配置 (3个SPI)

引脚的工作模式设置

引脚必须要按照这个表格配置。

二。SPI寄存器库函数配置

(一)常用寄存器

(二)SPI相关库函数

STM32的SPI接口可以配置为支持SPI协议或者支持I2S音频协议。默认是SPI模式,可以通过软件切换到I2S方式。

常用的函数:

1 void SPI_Init(SPI_TypeDef SPIx, SPI_InitTypeDef

SPI_InitStruct);//SPI的初始化

2 void SPI_Cmd(SPI_TypeDef SPIx, FunctionalState NewState); //SPI使能

3 void SPI_I2S_ITConfig(SPI_TypeDef SPIx, uint8_t SPI_I2S_IT,

FunctionalState NewState); //开启中断

4 void SPI_I2S_DMACmd(SPI_TypeDef SPIx, uint16_t SPI_I2S_DMAReq,

FunctionalState NewState);//通 过DMA传输数据

5 void SPI_I2S_SendData(SPI_TypeDef SPIx, uint16_t Data); //发送数据

6 uint16_t SPI_I2S_ReceiveData(SPI_TypeDef SPIx); //接收数据

7 void SPI_DataSizeConfig(SPI_TypeDef SPIx, uint16_t SPI_DataSize);

//设置数据是8位还是16位

8 其他几个状态函数

void SPI_Init(SPI_TypeDef SPIx, SPI_InitTypeDef

SPI_InitStruct);//SPI的初始化

结构体成员变量比较多,这里我们挑取几个重要的成员变量讲解一下:

第一个参数 SPI_Direction 是用来设置 SPI 的通信方式,可以选择为半双工,全双工,以及串行发和串行收方式,这里我们选择全双工模式

SPI_Direction_2Lines_FullDuplex。

第二个参数 SPI_Mode 用来设置 SPI 的主从模式,这里我们设置为主机模式 SPI_Mode_Master,当然有需要你也可以选择为从机模式

SPI_Mode_Slave。

第三个参数 SPI_DataSiz 为 8 位还是 16 位帧格式选择项,这里我们是 8 位传输,选择SPI_DataSize_8b。

第四个参数 SPI_CPOL 用来设置时钟极性,我们设置串行同步时钟的空闲状态为高电平所以我们选择 SPI_CPOL_High。

第五个参数 SPI_CPHA

用来设置时钟相位,也就是选择在串行同步时钟的第几个跳变沿(上升或下降)数据被采样,可以为第一个或者第二个条边沿采集,这里我们选择第二个跳变沿,所以选择

SPI_CPHA_2Edge

第六个参数 SPI_NSS 设置 NSS 信号由硬件(NSS 管脚)还是软件控制,这里我们通过软件控

制 NSS 关键,而不是硬件自动控制,所以选择 SPI_NSS_Soft。

第七个参数 SPI_BaudRatePrescaler 很关键,就是设置 SPI 波特率预分频值也就是决定 SPI 的时

钟的参数 , 从不分频道 256 分频 8 个可选值,初始化的时候我们选择 256 分频值

SPI_BaudRatePrescaler_256, 传输速度为 36M/256=140625KHz。

第八个参数 SPI_FirstBit 设置数据传输顺序是 MSB 位在前还是 LSB 位在前, ,这里我们选择

SPI_FirstBit_MSB 高位在前。

第九个参数 SPI_CRCPolynomial 是用来设置 CRC 校验多项式,提高通信可靠性,大于 1 即可。

设置好上面 9 个参数,我们就可以初始化 SPI 外设了。

初始化的范例格式为:

SPI_InitTypeDef SPI_InitStructure;

SPI_InitStructureSPI_Direction = SPI_Direction_2Lines_FullDuplex;

//双线双向全双工

SPI_InitStructureSPI_Mode = SPI_Mode_Master; //主 SPI

SPI_InitStructureSPI_DataSize = SPI_DataSize_8b; // SPI 发送接收 8 位帧结构

SPI_InitStructureSPI_CPOL = SPI_CPOL_High;//串行同步时钟的空闲状态为高电平

371

SPI_InitStructureSPI_CPHA = SPI_CPHA_2Edge;//第二个跳变沿数据被采样

SPI_InitStructureSPI_NSS = SPI_NSS_Soft; //NSS 信号由软件控制

SPI_InitStructureSPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //预分频

256

SPI_InitStructureSPI_FirstBit = SPI_FirstBit_MSB; //数据传输从 MSB 位开始

SPI_InitStructureSPI_CRCPolynomial = 7; //CRC 值计算的多项式

SPI_Init(SPI2, &SPI_InitStructure); //根据指定的参数初始化外设 SPIx 寄存器

(三)程序配置步骤

三。W25Qxx配置讲解

(一)电路图

片选用的PB12

W25Q64 是华邦公司推出的大容量SPI FLASH 产品,W25Q64 的容量为 64Mb,该系列还有 W25Q80/16/32

等。ALIENTEK 所选择的 W25Q64 容量为 64Mb,也就是 8M 字节。(1M=1024K)

W25Q64 将 8M 的容量分为 128 个块(Block),每个块大小为 64K 字节,每个块又分为 16个扇区(Sector),每个扇区 4K

个字节。W25Q64 的最少擦除单位为一个扇区,也就是每次必须擦除 4K 个字节。这样我们需要给 W25Q64 开辟一个至少 4K 的缓存区,这样对 SRAM

要求比较高,要求芯片必须有 4K 以上 SRAM 才能很好的 *** 作。

W25Q64 的擦写周期多达 10W 次,具有 20 年的数据保存期限,支持电压为 27~36V,W25Q64 支持标准的

SPI,还支持双输出/四输出的 SPI,最大 SPI 时钟可以到 80Mhz(双输出时相当于 160Mhz,四输出时相当于 320M),更多的 W25Q64

的介绍,请参考 W25Q64 的DATASHEET。

在往一个地址写数据之前,要先把这个扇区的数据全部读出来保存在缓存里,然后再把这个扇区擦除,然后在缓存中修改要写的数据,然后再把整个缓存中的数据再重新写入刚才擦除的扇区中。

便于学习和参考再给大家分享些spi 的资料

stm32之SPI通信

>

以上就是关于STM32硬件SPI怎么判断数据发完了,是哪个标志位全部的内容,包括:STM32硬件SPI怎么判断数据发完了,是哪个标志位、玩转 ESP32 + Arduino (六) 硬件定时器, IIC, SPI、求SPI的SSD1306在linux下的测试程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/9435006.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存