ST意法半导体
直播中

青sky

8年用户 1239经验值
擅长:模拟技术
私信 关注
[问答]

无法在设置为SPI从机的MCU上接收数据要怎么解决?

尝试在配置为 SPI 从机的 MCU (L432KC) 上接收数据。我试过使用中断和 DMA,但没有成功。
我已经设置了这样的电路:1 个 MCU 充当主机,每 500 毫秒间隔发送 1、2、3(我将主机线路连接到示波器并且信号正确生成)。在配置为从机的另一个 MCU 上,我连接了一个 RGB LED,它应该对 1、2、3 做出反应。
这是我的代码(中断处理程序已注释)
  • #include "STM32l4xx.h"                  // Device header
  • //RGB led is common anode
  • #define RED_ON (GPIOB->ODR &=~(1<<1))
  • #define RED_OFF (GPIOB->ODR |=1<<1)
  • #define BLUE_ON (GPIOB->ODR &=~(1<<6))
  • #define BLUE_OFF (GPIOB->ODR |= 1<<6)
  • #define GREEN_ON (GPIOB->ODR &=~(1<<7))
  • #define GREEN_OFF (GPIOB->ODR |= 1<<7);
  • void SPI1_Slave_init(void);
  • void delayms(int count);
  • int SPI1_read(void);
  • void SPI1rx_DMA_init(int c);
  • int main()
  • {
  •         int c=1;
  •         SPI1_Slave_init();
  •         SPI1rx_DMA_init(c);
  •         RCC->AHB2ENR |= RCC_AHB2ENR_GPIOBEN;
  •         GPIOB->MODER &=~(3<<2 | 3<<12 | 3<<14);
  •         GPIOB->MODER |= 1<<2 | 1<<12 | 1<<14;
  •         GPIOB->ODR |= (1<<1 | 1<<6 | 1<<7);
  •         //NVIC_EnableIRQ(SPI1_IRQn);
  •         while(1)
  •         {
  •                 DMA1_Channel2->CCR |= DMA_CCR_EN;                        //enable channel
  •                 while(!(DMA1->ISR & DMA_ISR_TCIF2));                        //wait till channel 2 transfer is complete
  •                 switch(c)
  •                 {
  •                         case 1: GREEN_OFF;
  •                         BLUE_OFF;
  •                         RED_ON;
  •                         break;
  •                         case 2: RED_OFF;
  •                         BLUE_OFF;
  •                         GREEN_ON;
  •                         break;
  •                         case 3: RED_OFF;
  •                         GREEN_OFF;
  •                         BLUE_ON;
  •                         break;
  •                 }
  •                 DMA1->IFCR |= DMA_IFCR_CTCIF2;
  •                 DMA1_Channel2->CCR &=~ (DMA_CCR_EN);                //disable channel
  •         }
  • }
  • void SPI1_Slave_init(void)
  • {
  •         RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
  •         RCC->AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
  •         GPIOA->MODER &=~(3<<8 | 3<<10 | 3<<12 | 3<<14);
  •         GPIOA->MODER |= (2<<8 | 2<<10 | 2<<12 | 2<<14);                        //set as AF
  •         GPIOA->AFR[0] &=~(0xF<<16 | 0XF<<20 | 0xF<<24 | 0xF<<28);
  •         GPIOA->AFR[0] |= (5<<16 | 5<<20 | 5<<24 | 5<<28);                                //AF5
  •         SPI1->CR1 &=~ (SPI_CR1_SPE);                        //disable SPI
  •         SPI1->CR1 &=~ (SPI_CR1_SSI | SPI_CR1_SSM | SPI_CR1_MSTR);                        //slave
  •         SPI1->CR1 |= (1<<3);                        // 1MHz baud rate
  •         SPI1->CR2 &= ~(0xF<<8);
  •         SPI1->CR2 |= 7<<8;                                //8 bit data
  •         //SPI1->CR2 |= SPI_CR2_RXNEIE;                        //enable RXNE interrupt
  •         SPI1->CR1 |= SPI_CR1_SPE;
  • }
  • void SPI1rx_DMA_init(int c)
  • {
  •         RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
  •         //DMA channel config
  •         DMA1_Channel2->CCR &=~(DMA_CCR_EN);
  •         DMA1_Channel2->CCR &=~(DMA_CCR_DIR);
  •         DMA1_Channel2->CNDTR = 1;
  •         DMA1_Channel2->CPAR = (uint32_t)&SPI1->DR;
  •         DMA1_Channel2->CMAR = (uint32_t)c;
  •         DMA1_CSELR->CSELR |= 1<<4;                                //DMA1 Channel 2 mapped to request no 2 (SPI1_RX)
  •         SPI1->CR2 |= SPI_CR2_RXDMAEN;
  • }
  • /*
  • void SPI1_IRQHandler(void)
  • {
  •         uint8_t c;
  •         if(SPI1->SR & SPI_SR_RXNE)
  •         {
  •                 c = *(__IO uint8_t *)&SPI1->DR;
  •                 switch(c)
  •                 {
  •                         case 1: GREEN_OFF;
  •                         BLUE_OFF;
  •                         RED_ON;
  •                         break;
  •                         case 2: RED_OFF;
  •                         BLUE_OFF;
  •                         GREEN_ON;
  •                         break;
  •                         case 3: RED_OFF;
  •                         GREEN_OFF;
  •                         BLUE_ON;
  •                         break;
  •                 }
  •         }
  • }
  • */
我已经分别测试了代码的 LED 部分,闪烁 R、G 和 B,它也工作正常。
同样,分别测试了中断和 DMA,因此在代码中忽略一个而考虑另一个。我也用普通的接收子程序测试过它,但无论如何我对它没有太大希望。
只是无法在从机上接收数据。我究竟做错了什么?
编辑:这是示波器上的波形。当与从设备断开连接时,波形是完美的。但是,当我将主机连接到从机时,会出现一些噪声,并且 SCL 线的幅度为 900mV。






回帖(1)

李渔滢

2023-2-6 09:52:32
> 我已经添加了示波器的波形,请检查一下。当连接这个从属设备时,SCL 线变得疯狂。
那是 SCK 对抗被设置为高的引脚。检查您的连接,也许来自主控的 SCK 与从属的 SCK 不同。
奴隶是像 Disco 还是 Nucleo 之类的东西?如果是,所有相关的板载连接(跳线、焊桥)是否断开?
举报

更多回帖

发帖
×
20
完善资料,
赚取积分