【转】spi测试自发自收(中断通信方式)

1、初始化spi时钟

1 void spiRccinit(void)
2 {
3     RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
4
5     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
6
7     RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
8 }

2、配置spi的GPIO引脚

 1 void spiGPIOInit(void)
 2 {
 3     GPIO_InitTypeDef gpio_init;
 4     gpio_init.GPIO_Pin = GPIO_Pin_4; //片选
 5     gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
 6     gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
 7     GPIO_Init(GPIOA, &gpio_init);
 8
 9     gpio_init.GPIO_Pin = GPIO_Pin_5;  //时钟
10     gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
11     GPIO_Init(GPIOA, &gpio_init);
12
13     gpio_init.GPIO_Pin = GPIO_Pin_7;  //MOSI
14     GPIO_Init(GPIOA, &gpio_init);
15
16     gpio_init.GPIO_Pin = GPIO_Pin_6;  //MISO
17     GPIO_Init(GPIOA, &gpio_init);
18 } 

3、配置并使能spi

 1 void spiConfigure(void)
 2 {
 3     SPI_InitTypeDef spi_Init;
 4     spi_Init.SPI_CPHA = SPI_CPHA_2Edge;
 5     spi_Init.SPI_CPOL = SPI_CPOL_Low;
 6     spi_Init.SPI_DataSize = SPI_DataSize_8b;
 7     spi_Init.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
 8     spi_Init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
 9     spi_Init.SPI_FirstBit = SPI_FirstBit_MSB;
10     spi_Init.SPI_Mode = SPI_Mode_Master;
11     spi_Init.SPI_NSS = SPI_NSS_Soft;
12     spi_Init.SPI_CRCPolynomial = 7;
13
14     SPI_Init(SPI1, &spi_Init);
15     SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE);
16     SPI_Cmd(SPI1,ENABLE);
17 } 

4、配置spi中断

 1 void spiNivcConfiguration(void)
 2 {
 3     NVIC_InitTypeDef nvic_init;
 4
 5     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
 6     nvic_init.NVIC_IRQChannel = SPI1_IRQn;
 7     nvic_init.NVIC_IRQChannelPreemptionPriority = 2;
 8     nvic_init.NVIC_IRQChannelSubPriority = 1;
 9     nvic_init.NVIC_IRQChannelCmd = ENABLE;
10
11     NVIC_Init(&nvic_init);
12 } 

5、实现中断处理函数

 1 void SPI1_IRQHandler(void)
 2 {
 3     if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != RESET)
 4     {
 5         if(send[++sendCount] != ‘\0‘)
 6         {
 7             SPI_I2S_SendData(SPI1, send[sendCount]);
 8         }
 9         else
10         {
11             SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_TXE, DISABLE);
12         }
13     }
14     if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != RESET)
15     {
16         recv[recvCount] = SPI_I2S_ReceiveData(SPI1);
17         if(recv[recvCount] == ‘*‘)
18         {
19             recv[recvCount + 1] = ‘\0‘;
20             printf("recv data: %s\r\n", recv);
21             recvCount = 0;
22         }
23         else
24         {
25             recvCount++;
26             if(recvCount == 1023)
27        {
28                 recvCount = 0;
29             }
30         }
31     }
32 }            

注:中断函数里用到的变量均为全局变量:

1 u8 recv[1024] = {‘\0‘};
2 u8 send[1024] = {‘\0‘};
3 volatile u16 recvCount = 0;
4 volatile u16 sendCount = 0;

6、实现简单的发送函数:

 1 void spiWrite(const char *p)
 2 {
 3     strcpy(send, p);
 4     sendCount = 0;
 5 //  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
 6     SPI_I2S_SendData(SPI1, send[sendCount]);
 7     SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_TXE, ENABLE);
 8 //  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
 9 //  recv[0] = SPI_I2S_ReceiveData(SPI1);
10 //  recv[1] = ‘\0‘;
11 //  printf("recv ok! ");
12 //  printf(recv);
13 }

7、总结:

  • 仔细阅读stm32 datasheet关于spi的部分
  • 配置spi时钟(一定要先初始化时钟)
  • 配置spi的gpio引脚
  • 配置spi
  • 配置中断
  • 实现中断处理函数
  • 简单实现发送函数

8、遗留问题:   

  采用中断发送的方式,发现在关闭掉SPI中断后(SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_TXE, DISABLE)),还是能进入到发送中断中,所以sendCount的清零要注意,最好不要在中断中。

  原因:猜测是stm32执行SPI_I2S_ITConfig函数时要花费一定的时间,而spi的发送中断在此期间会不断进入。

来源

原文地址:https://www.cnblogs.com/skullboyer/p/8378856.html

时间: 2024-08-30 16:23:16

【转】spi测试自发自收(中断通信方式)的相关文章

基于树莓派的Linux串口编程_实现自发自收

串口是计算机上一种非常通用设备通信的协议,常用PC机上包含的是RS232规格的串口,具有连接线少,通讯简单,得到广泛的使用. Linux对所有设备的访问是通过设备文件来进行的,串口也是这样,为了访问串口,只需打开其设备文件即可操作串口设备.在linux系统下面,每一个串口设备都有设备文件与其关联,设备文件位于系统的/dev目录下面.如linux下的/ttyS0,/ttyS1分别表示的是串口1和串口2. 树莓派UART端口的位置:见下图的GPIO14(TXD).GPIO 15(RXD) 本文是基于

【视频】MHDD|VCR|PC3000测试总汇 硬盘收卖佬必备神器

此三样工具,如医生之听筒,消防员之眼睛,硬盘收卖佬居家必备之良药!小编自当个活雷锋,你肯学,我肯教,拿走不谢!(视频体积较大,强烈建议WIFI下观看,土豪可忽略!) MHDD 硬盘测试 VCR 硬盘测试 PC3000硬盘测试

嵌入式linux串口通信自发自收测试程序

/*串口自收自发程序主函数*/#include"uart_api.h"int main(){ int fd; char buff[BUFFER_SIZE]; char buff2[]="Hello NUAA2440!\n"; int nread,nwrite; if((fd=open_port(TARGET_COM_PORT))<0) {  perror("open serial error");  return 1; } printf(&

android sdk manager无法更新(2014-11-6测试OK)--自己收藏用

问题描述: Android SDK Manager 无法下载更新,或者更新速度超慢,或者待安装包列表不显示. 解决方法: 第一,我们先修改下hosts文件.该文件的位置在系统盘(一般为C盘),具体路径为: C:\Windows\System32\ drivers\etc\hosts.找到该文件后,我们需要对该文件进行修改,可能有些同学发现会修改不了文件,这可能是因为hosts文件被设置成了只读属性,我们可以将其只读属性取消掉,如图1,在文件属性中,将图1中的勾取消掉即可. 图1 hosts文件的

MSM8909+Android5.1.1 SPI驱动开发(PSAM部分)

MSM8909+Android5.1.1SPI驱动开发(PSAM部分) 1.     PSAM部分的硬件设计 图1 CS   片选信号 SCK  时钟信号 MISO 主设备的数据输入.从设备的数据输出脚 MOSI 主设备的数据输出.从设备的数据输入脚 2.     PSAM部分软件设计 图2 (1)  PSAM应用 这部分只需要调用API函数即可. (2)  PSAM API API的主要工作就是给M0上电.设置SPI读写模式.设置SPI读写的每字节的位数.SPI的工作频率等. (3)  SPI

DPDK--Skeleton 单核收发包测试案例 源码阅读

#include <stdint.h> #include <inttypes.h> #include <rte_eal.h> #include <rte_ethdev.h> #include <rte_cycles.h> #include <rte_lcore.h> #include <rte_mbuf.h> #define RX_RING_SIZE 128 //接收环大小 #define TX_RING_SIZE 512

三,ESP8266 SPI

重点是说SPI通信协议,,,, 不要害怕协议因为协议是人规定的,,刚好我也是人......规定的协议既然能成为规范让所有人所接受,那么必然有它的优势和优点,必然值得学习,, 害怕协议的人是因为当初碰到了不懂的老师,他只会告诉你这很难............其实是他不会........ CS      :   Chip Selection    片选引脚,多个设备时可以用这个引脚选择和哪个设备通信 MOSI  :   Master Out   Slave In   主机输出数据引脚,,,,从机接收

SPI、I2C、UART、I2S、GPIO、SDIO、CAN

总线,总线,总要陷进里面.这世界上的信号都一样,但是总线却成千上万,让人头疼. 总的来说,总线有三种:内部总线.系统总线和外部总线.内部总线是微机内部各外围芯片与处理器之间的总线,用于芯片一级的互连:而系统总线是微机中各插件板与系统板之间的总线,用于插件板一级的互连:外部总线则是微机和外部设备之间的总线,微机作为一种设备,通过该总线和其他设备进行信息与数据交换,它用于设备一级的互连. 除了总线外,还有一些接口,它们是多种总线的集合体,或者说来者不拒. SPI (Serial Peripheral

【转载】app测试的过程和重点关注内容

针对 app测试的过程和重点关注内容,做以下梳理和总结: 1 . 首先是测试资源确认及准备 ( 1 ) 产品需求文档.产品原型图.接口说明文档以及设计说明文档等应齐全: ( 2 ) 测试设备及工具的准备: IOS 和 andriod 不同版本的真机,以及相关测试工具的准备. 2 . 测试用例的设计与评审 ( 1 ) 根据产品需求文档.产品原型图等文档,设计客户端的一般功能测试用例: ( 2 ) 测试用例评审.修改与完善,评审通过后着手进入正式测试阶段. 3 . UI 测试 ( 1 ) 确保手头的