单片机
返回首页

解决STM32 SPI 半残废 NSS无法拉高

2019-07-01 来源:eefocus

众所周知,STM32  SPI是个半残废,NSS无法自动拉高,所以使用SPI 从机会一直使能,当主机是一对多的时候,就会出现SPI从机互相干扰的问题。

我利用GPIO中断,代替NSS引脚,使用过程如下代码所示

1.初始化SPI  的IO口,其中NSS引脚先不管。

 

  1. void GPIO_SPI12_Config(void)

  2. {

  3. GPIO_InitTypeDef GPIO_InitStructure;

  4. //----- 第1步:打开SPI部件的时钟 --------------------------------------------------------------------------------------------

  5. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

  6. //----- 第2步:打开SPI相关的引脚为复用推挽输出 -----------------------------------------------------------------------------

  7.  

  8.  

  9. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  10. GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  11. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

  12. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3;

  13.  

  14. /* SPI SCK pin configuration */

  15. GPIO_InitStructure.GPIO_Pin = SPI12_SCK_PIN;

  16. GPIO_Init(SPI12_SCK_GPIO_PORT, &GPIO_InitStructure);

  17.  

  18. /* SPI MOSI pin configuration */

  19. GPIO_InitStructure.GPIO_Pin = SPI12_MOSI_PIN;

  20. GPIO_Init(SPI12_MOSI_GPIO_PORT, &GPIO_InitStructure);

  21.  

  22. /* SPI MISO pin configuration */

  23. GPIO_InitStructure.GPIO_Pin = SPI12_MISO_PIN;

  24. GPIO_Init(SPI12_MISO_GPIO_PORT, &GPIO_InitStructure);

  25. // STM32 SPI 的CS引脚不会自动拉高,所以用GPIO中断代替

  26.  

  27. // GPIO_InitStructure.GPIO_Pin = SPI12_CS_PIN;

  28. // GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

  29. // GPIO_Init(SPI12_CS_GPIO_PORT, &GPIO_InitStructure);

  30.  

  31. GPIO_PinAFConfig(SPI12_SCK_GPIO_PORT, SPI12_SCK_SOURCE, SPI12_SCK_AF);

  32. GPIO_PinAFConfig(SPI12_MOSI_GPIO_PORT, SPI12_MOSI_SOURCE, SPI12_MOSI_AF);

  33. GPIO_PinAFConfig(SPI12_MISO_GPIO_PORT, SPI12_MISO_SOURCE, SPI12_MISO_AF);

  34. // GPIO_PinAFConfig(SPI12_CS_GPIO_PORT, SPI12_CS_SOURCE, SPI12_CS_AF);

  35.  

  36. }

 

 

2.再初始化SPI,初始化方式是从机子模式,这时候先不要使能SPI。

 
  1. void SPI12_Config(void)

  2. {

  3. SPI_InitTypeDef SPI_InitStructure;

  4. SPI_RxFIFOThresholdConfig(SPI1,SPI_RxFIFOThreshold_QF);

  5. //----- 第3步:配置SPI的参数设定 --------------------------------------------------------------------------------------------

  6. SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线双向全双工

  7. SPI_InitStructure.SPI_Mode = SPI_Mode_Slave; //设置为主模式SPI

  8. SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //发送接收8 位数据

  9. SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟悬空为低

  10. SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //数据捕获于第二个时钟沿

  11. SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS 信号由软件管理

  12. SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; //设置波特率为去64 分频

  13. SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //数据传输从MSB 位开始

  14. SPI_InitStructure.SPI_CRCPolynomial = 7; //校验

  15. SPI_Init(SPI1, &SPI_InitStructure);

  16. SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Tx,DISABLE);

  17. SPI_I2S_DMACmd(SPI1,SPI_I2S_DMAReq_Rx,DISABLE);

  18. SPI_ITConfig(SPI1, SPI_IT_RXNE,DISABLE); //接收中断失能

  19. SPI_ITConfig(SPI1, SPI_IT_TXE, DISABLE); //发送中断失能

  20. //----- 第4步:使能SPI1, 配置完毕 ------------------------------------------------------------------------------------------

  21. SPI_Cmd(SPI1, DISABLE);

  22. }


 

 

 3. 将NSS引脚配置成GPIO中断,这里NSS 引脚为PA15,配置过程如下代码

 
  1. void Exti_15_Init(void)

  2. {

  3. NVIC_InitTypeDef NVIC_InitStructure;

  4. GPIO_InitTypeDef GPIO_InitStructure;

  5. EXTI_InitTypeDef EXTI_InitStructure;

  6.  

  7. RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); // 配置中断时钟

  8. //----- 设置外部中断引脚,用户根据实际情况自行修改 ------------------------------------------------------------------------------

  9.  

  10. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;

  11. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; // 输入

  12. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_2; // 快速

  13. GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉

  14.  

  15. GPIO_Init(GPIOA, &GPIO_InitStructure);

  16.  

  17. //----- 设置NVIC初始化 ------------------------------------------------------------------------------

  18.  

  19. NVIC_InitStructure.NVIC_IRQChannel = EXTI4_15_IRQn; // 中断通道

  20. NVIC_InitStructure.NVIC_IRQChannelPriority = 0; // 中断优先级(0-3)

  21. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; // 使能

  22.  

  23. NVIC_Init(&NVIC_InitStructure);

  24.  

  25. SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, GPIO_PinSource15); //连接中断线路

  26. EXTI_InitStructure.EXTI_Line = EXTI_Line15; //设置中断线路

  27. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

  28. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; //双沿触发

  29. EXTI_InitStructure.EXTI_LineCmd = ENABLE; //中断线使能

  30. EXTI_Init(&EXTI_InitStructure); //初始化中断

  31. }


 

 

4. 写GPIO中断服务函数,该函数的主要工作判断NSS引脚的电平,若NSS为低电平则使能SPI,否则失能SPI。

 
  1. void SPI1_NSS_Handler(void)

  2. {

  3. if(GPIO_ReadInputDataBit(SPI12_CS_GPIO_PORT,SPI12_CS_PIN)!=RESET)

  4. {

  5. SPI_Cmd(SPI1,DISABLE);

  6. }

  7. else

  8. {

  9. SPI_Cmd(SPI1,ENABLE);

  10. }

  11. }

  12.  

  13. void EXTI4_15_IRQHandler(void)

  14. {

  15. if(EXTI_GetITStatus(EXTI_Line15) != RESET)

  16. {

  17. EXTI_ClearITPendingBit(EXTI_Line15);

  18. SPI1_NSS_Handler();

  19. }

  20. }


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • 开关电源的基本组成及工作原理

  • 带有短路保护系统的5V直流稳压电源电路图

  • 如何构建一个触摸传感器电路

  • 如何调制IC555振荡器

  • 基于ICL296的大电流开关稳压器电源电路

    相关电子头条文章