stm32 spi的测试例程

发布者:清新心情最新更新时间:2019-08-09 来源: eefocus关键字:stm32  spi  测试例程 手机看文章 扫描二维码
随时随地手机看文章

/* 自定义同义关键字 ——————————————————–*/


typedef enum {FAILED = 0, PASSED = !FAILED} TestStatus;


/* 自定义参数宏 ——————————————————–*/


define BufferSize 32

/* 自定义函数宏 ——————————————————–*/


/* 自定义全局变量 ——————————————————–*/


SPI_InitTypeDef SPI_InitStructure; /* 定义 SPI 初始化结构体 */


u8 SPI1_Buffer_Tx[BufferSize] = /* 定义待 SPI1 传输数据 */ 

0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 

0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10, 

0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18, 

0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20 

};


u8 SPI2_Buffer_Tx[BufferSize] = /* 定义待 SPI2 传输数据 */ 

0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58, 

0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60, 

0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68, 

0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70 

};


u8 SPI1_Buffer_Rx[BufferSize]; /* 开辟内存空间待 SPI1 接收 */ 

u8 SPI2_Buffer_Rx[BufferSize]; /* 开辟内存空间待 SPI2 接收 */ 

u8 Tx_Idx = 0; /* 发送计数变量 */ 

u8 Rx_Idx = 0; /* 接收计数变量 */ 

vu8 k = 0 , i = 0; /* 循环计数变量 */


/* 自定义函数声明 ——————————————————–*/


void RCC_Configuration(void); 

void GPIO_Configuration(void); 

void SPI_Configuration(void); 

void USART_Configuration(void);


/********************************************************************* 

* 函数名 : main 

* 函数描述 : main 函数 

* 输入参数 : 无 

* 输出结果 : 无 

* 返回值 : 无 

*********************************************************************/


int main(void) 

/* 设置系统时钟 */ 

RCC_Configuration();


/* 设置 GPIO 端口 */

GPIO_Configuration();


/* 设置 SPI */

SPI_Configuration();


/* 设置 USART */

USART_Configuration();


/* 设置 SPI2 为主机*/

SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

SPI_Init(SPI1, &SPI_InitStructure); 

/* 设置 SPI2 为从机*/

SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

SPI_Init(SPI2, &SPI_InitStructure);


while(Tx_Idx < BufferSize)

    /* 等待 SPI1 发送缓冲空 */ 

    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

    /* SPI2 发送数据 */ 

    SPI_I2S_SendData(SPI2, SPI2_Buffer_Tx[Tx_Idx]); 

    /* SPI1 发送数据 */  

    SPI_I2S_SendData(SPI1, SPI1_Buffer_Tx[Tx_Idx++]);


    /* 等待 SPI2 接收数据完毕 */

    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

    /* 读出 SPI2 接收的数据 */ 

    SPI2_Buffer_Rx[Rx_Idx] = SPI_I2S_ReceiveData(SPI2);


    /* 等待 SPI1 接收数据完毕 */ 

    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

    /* 读出 SPI1 接收的数据 */ 

    SPI1_Buffer_Rx[Rx_Idx++] = SPI_I2S_ReceiveData(SPI1);        

}


/* 打印试验结果信息 ---------------------------------------------------------------------------------------------*/


printf("rnThe First transfer between the two SPI perpherals: The SPI1 Master and the SPI2 slaver. rn");


printf("rnThe SPI1 has sended data below: rn");

for(k = 0; k < BufferSize ; k ++)

{

    printf("%0.2d r" , *(SPI1_Buffer_Tx + k));

    for(i = 0 ; i < 200 ; i ++);

}

printf("rnThe SPI2 has receive data below: rn");

for(k = 0; k < BufferSize ; k ++)

{

    printf("%0.2d r" , *(SPI2_Buffer_Rx + k));

    for(i = 0 ; i < 200 ; i ++);

}


printf("rn rn");


printf("rnThe SPI2 has sended data below: rn");

for(k = 0; k < BufferSize ; k ++)

{

    printf("%0.2d r" , *(SPI2_Buffer_Tx + k));

    for(i = 0 ; i < 200 ; i ++);

}

printf("rnThe SPI1 has receive data below: rn");

for(k = 0; k < BufferSize ; k ++)

{

    printf("%0.2d r" , *(SPI1_Buffer_Rx + k));

    for(i = 0 ; i < 200 ; i ++);

}


/* 打印试验结果信息 ---------------------------------------------------------------------------------------------*/



Tx_Idx=0;

Rx_Idx=0;

for(k=0; k < BufferSize; k++)  

{

    *(SPI2_Buffer_Rx + k) = 0;

}

for(k=0; k < BufferSize; k++)

{

    *(SPI1_Buffer_Rx + k) = 0;

}



/* 设置 SPI2 为主机*/

SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

SPI_Init(SPI2 , &SPI_InitStructure);    

/* 设置 SPI1 为从机*/

SPI_InitStructure.SPI_Mode = SPI_Mode_Slave;

SPI_Init(SPI1 , &SPI_InitStructure);


while(Tx_Idx < BufferSize)

    /* 等待 SPI2 发送缓冲空 */ 

    while(SPI_I2S_GetFlagStatus(SPI2 , SPI_I2S_FLAG_TXE) == RESET);

    /* SPI1 发送数据 */ 

    SPI_I2S_SendData(SPI1 , SPI1_Buffer_Tx[Tx_Idx]);

    /* SPI2 发送数据 */ 

    SPI_I2S_SendData(SPI2 , SPI2_Buffer_Tx[Tx_Idx++]);


    /* 等待 SPI1 接收数据完毕 */ 

    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

    /* 读出 SPI1 接收的数据 */

    SPI1_Buffer_Rx[Rx_Idx] = SPI_I2S_ReceiveData(SPI1);


    /* 等待 SPI2 接收数据完毕 */ 

    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);

    /* 读出 SPI2 接收的数据 */

    SPI2_Buffer_Rx[Rx_Idx++] = SPI_I2S_ReceiveData(SPI2); 

}


/* 打印试验结果信息 ---------------------------------------------------------------------------------------------*/


printf("rn rnThe Second transfer between the two SPI perpherals: The SPI2 Master and the SPI1 slaver.  rn");


printf("rnThe SPI2 has sended data below: rn");

for(k = 0; k < BufferSize ; k ++)

{

    printf("%0.2d r" , *(SPI2_Buffer_Tx + k));

    for(i = 0 ; i < 200 ; i ++);

}

printf("rnThe SPI1 has receive data below: rn");

for(k = 0; k < BufferSize ; k ++)

{

    printf("%0.2d r" , *(SPI1_Buffer_Rx + k));

    for(i = 0 ; i < 200 ; i ++);

}


printf("rn rn");


printf("rnThe SPI1 has sended data below: rn");

for(k = 0; k < BufferSize ; k ++)

{

    printf("%0.2d r" , *(SPI1_Buffer_Tx + k));

    for(i = 0 ; i < 200 ; i ++);

}

printf("rnThe SPI2 has receive data below: rn");

for(k = 0; k < BufferSize ; k ++)

{

    printf("%0.2d r" , *(SPI2_Buffer_Rx + k));

    for(i = 0 ; i < 200 ; i ++);

}

/* 打印试验结果信息 ---------------------------------------------------------------------------------------------*/


while(1);


}


/********************************************************************* 

* 函数名 : RCC_Configuration 

* 函数描述 : 设置系统各部分时钟 

* 输入参数 : 无 

* 输出结果 : 无 

* 返回值 : 无 

*********************************************************************/


void RCC_Configuration(void) 

/* 定义枚举类型变量 HSEStartUpStatus */ 

ErrorStatus HSEStartUpStatus;


/* 复位系统时钟设置 */

RCC_DeInit();


/* 开启 HSE */

RCC_HSEConfig(RCC_HSE_ON);


/* 等待 HSE 起振并稳定 */

HSEStartUpStatus = RCC_WaitForHSEStartUp();


/* 判断 HSE 起是否振成功,是则进入if()内部 */

if(HSEStartUpStatus == SUCCESS)

{

    /* 选择 HCLK(AHB)时钟源为SYSCLK 1分频 */

    RCC_HCLKConfig(RCC_SYSCLK_Div1); 


    /* 选择 PCLK2 时钟源为 HCLK(AHB) 1分频 */

    RCC_PCLK2Config(RCC_HCLK_Div1); 


    /* 选择 PCLK1 时钟源为 HCLK(AHB) 2分频 */

    RCC_PCLK1Config(RCC_HCLK_Div2);


    /* 设置 FLASH 延时周期数为2 */

    FLASH_SetLatency(FLASH_Latency_2);


    /* 使能 FLASH 预取缓存 */

    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);


    /* 选择锁相环(PLL)时钟源为HSE 1分频,倍频数为9,则PLL输出频率为 8MHz * 9 = 72MHz */

    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);


    /* 使能 PLL */ 

    RCC_PLLCmd(ENABLE);


    /* 等待 PLL 输出稳定 */

    while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);


    /* 选择 SYSCLK 时钟源为 PLL */

    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);


    /* 等待 PLL 成为 SYSCLK 时钟源 */

    while(RCC_GetSYSCLKSource() != 0x08);

}


/* 打开 SPI2 时钟 */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);

/* 打开 GPIOA,GPIOB,USART1 和 SPI1 时钟 */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | 

                       RCC_APB2Periph_USART1 |RCC_APB2Periph_SPI1, ENABLE);

}


/********************************************************************* 

* 函数名 : GPIO_Configuration 

* 函数描述 : 设置各GPIO端口功能 

* 输入参数 : 无 

* 输出结果 : 无 

* 返回值 : 无 

*********************************************************************/


void GPIO_Configuration(void) 

/* 定义 GPIO 初始化结构体 GPIO_InitStructure */ 

GPIO_InitTypeDef GPIO_InitStructure;


/* 设置 SPI1 引脚: SCK, MISO 和 MOSI */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_Init(GPIOA, &GPIO_InitStructure);


/* 设置 SPI2 引脚: SCK, MISO 和 MOSI */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

GPIO_Init(GPIOB, &GPIO_InitStructure);


/* 设置 USART1 的Tx脚(PA.9)为第二功能推挽输出功能 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA , &GPIO_InitStructure);


/* 设置 USART1 的Rx脚(PA.10)为浮空输入脚 */

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;

GPIO_Init(GPIOA , &GPIO_InitStructure);


}


/********************************************************************* 

* 函数名 : SPI_Configuration 

* 函数描述 : 设置 SPI 参数 

* 输入参数 : 无 

* 输出结果 : 无 

* 返回值 : 无 

*********************************************************************/


void SPI_Configuration(void) 

/* 

* SPI 设置为双线双向全双工 

* SPI 发送接收 8 位帧结构 

* 时钟悬空低 

* 数据捕获于第二个时钟沿 

* 内部 NSS 信号由 SSI 位控制 

* 波特率预分频值为 4 

* 数据传输从 LSB 位开始 

* 用于 CRC 值计算的多项式 

*/


SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;

SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;

SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB;

SPI_InitStructure.SPI_CRCPolynomial = 7;


/* 使能 SPI1 */

SPI_Cmd(SPI1, ENABLE);

/* 使能 SPI2 */

[1] [2]
关键字:stm32  spi  测试例程 引用地址:stm32 spi的测试例程

上一篇:STM32 flash读写程序
下一篇:stm32 I2C自收发测试例程

推荐阅读最新更新时间:2024-11-05 21:27

STM32学习之:事件标志组
为什么要使用事件标志 事件标志组是实现多任务同步的有效机制之一。也许有不理解的初学者会问采用事件标志组多麻烦, 搞个全局变量不是更简单?其实不然,在裸机编程时,使用全局变量的确比较方便,但是在加上 RTOS 后 就是另一种情况了。 使用全局变量相比事件标志组主要有如下三个问题:  使用事件标志组可以让 RTOS 内核有效地管理任务,而全局变量是无法做到的,任务的超时等机制需 要用户自己去实现。  使用了全局变量就要防止多任务的访问冲突,而使用事件标志组则处理好了这个问题,用户无需担心。  使用事件标志组可以有效地解决中断服务程序和任务之间的同步问题。 FreeRTOS 任务间事件标志组的实现 任务间事件标志组的实现是指各个
[单片机]
<font color='red'>STM32</font>学习之:事件标志组
STM32学习笔记之GPIO的基本使用
楼学习中主要使用的资料有 战舰V3资料盘——教学视频 《STM32F1开发指南-库函数版本_V3.1》 (PDF) 《零死角玩转STM32》 野火出版 使用的学习板为屹讯电子嵌入式平台v2(MCU为 STM32F103RCT6) **某些IO口带有FT标识,代表其最大工作电压达到5V CPU能直接读取外设电平 上拉电阻的作用????????????????? 下拉电阻 CPU能直接读取外部电压变化(模拟量) 0-3.3v 输出控制电路置1,输出由外部电路决定(上拉或下拉) 输出控制电路置0,输出为0 置1置0的写入由CPU执行 输出控制电路的写入由外设模块决定 输出控制电路置1,输出1;置0,输出0。
[单片机]
<font color='red'>STM32</font>学习笔记之GPIO的基本使用
stm32-esp8266驱动程序
esp8266模块是串口通讯,通讯的协议是AT指令,要正确的配置对应的AT指令模块才可以工作,这里就需要知道AT指令有没有配置成功,这个比较容易实现,一般发送AT指令配置成功的话,芯片都会返回至少一个OK,当然还有其它数据,我们只需要去解析有没有接收到OK就知道指令发送是否成功了。我这里是作为TCP客服端,所以只需要以下一些指令即可: 1 发送 ATrn 返回 OK 以上操作确保芯片连接正常,工作正常 2 发送 ATE0rn 返回 OK 关闭回显 3 发送 AT+CWMODE=1rn 返回 OK 设置成客服端模式 4 发送 AT+CIPSTATUS 返回 2 3 4 5 2
[单片机]
stm32-esp8266驱动程序
一文读懂STM32的基本系统
电源 无论是否使用模拟部分和AD部分,MCU外围出去VCC和GND,VDDA、VSSA、Vref(如果封装有该引脚)都必需要连接,不可悬空 对于每组对应的VDD和GND都应至少放置一个104的陶瓷电容用于滤波,并接该电容应放置尽量靠近MCU 用万用表测试供电电压是否正确,调试时最好用数字电源供电,以便过压或过流烧坏板子,电压最好一步一步从进线端测试到芯片供电端 复位、启动选择 Boot引脚与JTAG无关。其仅是用于MCU启动后,判断执行代码的起始地址 在电路设计上可能Boot引脚不会使用,但要求一定要外部连接电阻到地或电源,切不可悬空;STM32三种启动模式对应的存储介质均是芯片内置的,它们是: 用户闪存 = 芯片内置
[单片机]
一文读懂<font color='red'>STM32</font>的基本系统
stm32之时钟控制
本文提到的有以下内容: 时钟系统与总线矩阵 SysTick系统定时器 RTC实时时钟 看门狗定时器 通用定时器 一、时钟系统与总线矩阵   stm32F4的时钟树如下图所示:   在STM32中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。 HSI是高速内部时钟,RC振荡器,频率为8MHz。 HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。 LSI是低速内部时钟,RC振荡器,频率为40kHz。 LSE是低速外部时钟,接频率为32.768kHz的石英晶体。 PLL为锁相环倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为
[单片机]
<font color='red'>stm32</font>之时钟控制
STM32通用定时器的几个重要寄存器
1..自动装载寄存器部分实际上包含两个寄存器: 自动装载寄存器缓冲寄存器 和 自动装载寄存器影子寄存器 其中自动装载寄存器缓冲寄存器可以有ARPE位控制是否起作用: ARPE = 0 写 自动装载寄存器 时,数据直接写入到 自动装载寄存器缓冲寄存器 的同时,立即更新到 自动装载寄存器影子寄存器 ARPE = 1 写 自动装载寄存器 时,数据直接写入到 自动装载寄存器缓冲寄存器 的同时,只有更新事件发生的时候,才更新到 自动装载寄存器影子寄存器 2.预分频器控制寄存器也分为两部分: 预分频器缓冲寄存器 和 预分频器影子寄存器 当更新事件发生的时候, 预分频器缓冲寄存器 的内容更新到 预分频器影子寄存器中 3.UDIS位作用:
[单片机]
STM32驱动W25X64存储器
W25X64 是华邦公司推出的大容量 SPI FLASH 产品,W25X64 的容量为 64Mbit(8M),该系列还有 W25Q80/16/32 等。W25X16,W25X32,W25X64分别有8192,16384,32768个可编程页,每页256字节,用扇区擦除指令每次可以擦除16页,用块擦除指令每次可以擦除256页,用整片擦除指令既可以擦除整个芯片,W25X16,W25X32,W25X64分别有512,1024,2048个可擦除扇区,或者32,64,128个可擦除的块 W25Q64 的擦写周期多达 10W 次,具有 20 年的数据保存期限,支持电压为 2.7~3.6V, W25Q64 支持标准的 SPI,还支持双输出/四输
[单片机]
<font color='red'>STM32</font>驱动W25X64存储器
STM32 ucos 下添加CAN模块
1.CAN IO RX TX 的设定和重映射 GPIO_PinRemapConfig(GPIO_Remap2_CAN, ENABLE); //端口重映射到PD0,PD1 2.clock CAN IO CLOCK 的开启 、*-------gpio for can------------*/ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE); CAN 自身CLOCK 的开启、 /* CAN Periph clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved