工程文件参考——STM32+HAL+SPI主从机通讯

文章目录

  • 前言
  • CubeMX设置
  • SPI设置
  • NSS设置
  • SPI从机代码
  • SPI主机代码

  • 前言

    关于如何简单的写一个稳定的SPI主从机通讯,思路很简单
    1、SPI高速传输的时候很容易出现错位之类的问题,CRC的校验首先是必要的。在STM32中SPI使用DMA通讯可以自动执行CRC的校验,只需要在CubeMX设置SPI的CRC和DMA
    2、从机的NSS用硬件模式不是很好用,使用外部中断可以提供更多灵活的编写方式
    3、有个很坑的点,如果中间出现断连等问题,很容易出现数据错位,而且错了一次会一直错下去,所以检测到CRC错误后要自己将SPI模块的时钟重置


    CubeMX设置

    SPI设置



    我选的16bit传输,具体可以根据自己的硬件需求再改

    NSS设置

    选一个引脚做外部中断触发,上下沿都要

    注意这个代码生成后要手动在gpio.c文件中把HAL_NVIC_EnableIRQ(XXX);给屏蔽掉,不然刚开机这个端口就开始跳中断,提前跑了一些不该跑的,会出一些比较操蛋的错误

    SPI从机代码

    放在哪里都行

    //下降沿触发接收分析,校验数据是否正确
    void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)//虚函数定义,HAL库会自动调用过来
    {
    	if(GPIO_Pin == SPI1_NSS_Pin)
    	{
    		if((HAL_SPI_GetState(&hspi1) == HAL_SPI_STATE_READY) && HAL_SPI_GetError(&hspi1) == HAL_SPI_ERROR_NONE)
    		{
    			//数据正确,执行数据搬运
    		}
    		else//数据错误,重置SPI时钟
    		{
    			HAL_NVIC_DisableIRQ(EXTI4_15_IRQn);//注意改成自己的触发源
    			HAL_SPI_DMAStop(&hspi1);
    			__HAL_RCC_SPI1_FORCE_RESET();
    			__HAL_RCC_SPI1_RELEASE_RESET();
    			//HAL_SPI_DeInit(&hspi1);
    			HAL_SPI_Init(&hspi1);
    			HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);
    		}
    	}
    }
    
    //上降沿触发准备接收
    void HAL_GPIO_EXTI_Falling_Callback(uint16_t GPIO_Pin)
    {
    	if(GPIO_Pin == SPI1_NSS_Pin)
    	{
    		HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t*)spi1_tx_buf, (uint8_t*)spi1_rx_buf, 4);//1-2us
    	}
    }
    

    SPI主机代码

    主机直接定时跑就够了

    HAL_GPIO_WritePin(GPIOX, GPIO_PIN_X, GPIO_PIN_RESET);
    HAL_Delay(1);
    HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t*)spi1_tx_buf, (uint8_t*)spi1_rx_buf, 4);
    HAL_GPIO_WritePin(GPIOX, GPIO_PIN_X, GPIO_PIN_SET);
    

    CRC校验会自动在DMA传输完后自动再传输

    作者:某先森不吃鱼

    物联沃分享整理
    物联沃-IOTWORD物联网 » 工程文件参考——STM32+HAL+SPI主从机通讯

    发表回复