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

1、初始化spi时钟

void spiRccinit(void){  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

}

2、配置spi的GPIO引脚

void spiGPIOInit(void){
    GPIO_InitTypeDef gpio_init;
    gpio_init.GPIO_Pin = GPIO_Pin_4; //片选
    gpio_init.GPIO_Speed = GPIO_Speed_50MHz;
    gpio_init.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOA, &gpio_init);

    gpio_init.GPIO_Pin = GPIO_Pin_5;  //时钟
    gpio_init.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &gpio_init);

    gpio_init.GPIO_Pin = GPIO_Pin_7;  //MOSI 
    GPIO_Init(GPIOA, &gpio_init);

    gpio_init.GPIO_Pin = GPIO_Pin_6;  //MISO
    GPIO_Init(GPIOA, &gpio_init);

}
3、配置并使能spi

void spiConfigure(void){
    SPI_InitTypeDef spi_Init;
    spi_Init.SPI_CPHA = SPI_CPHA_2Edge;
    spi_Init.SPI_CPOL = SPI_CPOL_Low;
    spi_Init.SPI_DataSize = SPI_DataSize_8b;
    spi_Init.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
    spi_Init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
    spi_Init.SPI_FirstBit = SPI_FirstBit_MSB;
    spi_Init.SPI_Mode = SPI_Mode_Master;
    spi_Init.SPI_NSS = SPI_NSS_Soft;
    spi_Init.SPI_CRCPolynomial = 7;

    SPI_Init(SPI1, &spi_Init);  
    SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_RXNE,ENABLE); 
    SPI_Cmd(SPI1,ENABLE);

}
4、配置spi中断

void spiNivcConfiguration(void){

    NVIC_InitTypeDef nvic_init;     
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); 
    nvic_init.NVIC_IRQChannel = SPI1_IRQn;
    nvic_init.NVIC_IRQChannelPreemptionPriority = 2;
    nvic_init.NVIC_IRQChannelSubPriority = 1;
    nvic_init.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&nvic_init);

}
5、实现中断处理 函数

void SPI1_IRQHandler(void){
    if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != RESET){
        if(send[++sendCount] != '\0'){
            SPI_I2S_SendData(SPI1, send[sendCount]);
        }
        else {      
            SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_TXE, DISABLE);
        }
    }
    if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != RESET){
        recv[recvCount] = SPI_I2S_ReceiveData(SPI1);
        if(recv[recvCount] == '*'){
            recv[recvCount + 1] = '\0';
            printf("recv data: %s\r\n", recv);
            recvCount = 0;
        }
        else {
            recvCount++;                
            if(recvCount == 1023){
                recvCount = 0;
            }
        }
    }

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

u8 recv[1024] = {'\0'};
u8 send[1024] = {'\0'};
volatile u16 recvCount = 0;
volatile u16 sendCount = 0;

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

void spiWrite(const char *p){
    strcpy(send, p);
    sendCount = 0;
    //  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
    SPI_I2S_SendData(SPI1, send[sendCount]);
    SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_TXE, ENABLE);
//  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
//  recv[0] = SPI_I2S_ReceiveData(SPI1);
//  recv[1] = '\0';
//  printf("recv ok! ");
//  printf(recv);
}

7、总结:

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

8、遗留问题:

    采用中断发送的方式,发现在关闭掉SPI中断后(SPI_I2S_ITConfig(SPI1,SPI_I2S_IT_TXE, DISABLE)),
还是能进入到发送中断中,所以sendCount的清零要注意,最好不要在中断中。
原因:猜测是stm32执行SPI_I2S_ITConfig函数时要花费一定的时间,而spi的发送中断在此期间会不断进入。
  • 8
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
以下是使用STM32Cube HAL库进行SPI中断发送的基本步骤: 1. 配置SPI口 使用STM32CubeMX或手动编写代码配置SPI口。确保SPI口的时钟和引脚都已正确配置。 2. 配置SPI中断 使用HAL库的函数`HAL_SPI_Transmit_IT()`启动中断传输。此函数将发送缓冲区中的数据,并使能SPI的数据寄存器空中断(TXE中断)。 3. 实现SPI中断处理函数 在SPI中断处理函数(例如`HAL_SPI_TxCpltCallback()`)中,将发送缓冲区中的下一个字节加载到SPI数据寄存器中。如果所有数据都已发送,则禁用TXE中断并调用完成回调函数。 以下是一个简单的示例代码,演示了如何在STM32Cube HAL库中实现SPI中断发送: ```c #include "stm32f4xx_hal.h" #define BUFFER_SIZE 10 SPI_HandleTypeDef hspi1; uint8_t tx_buffer[BUFFER_SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A}; volatile uint8_t tx_index = 0; void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi) { if(tx_index == BUFFER_SIZE) { HAL_SPI_Transmit_IT(&hspi1, tx_buffer, BUFFER_SIZE); // 禁用TXE中断并重新启动传输以发送下一组数据 } else { hspi->Instance->DR = tx_buffer[tx_index++]; // 将下一个字节加载到SPI数据寄存器中 } } int main(void) { HAL_Init(); hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; if (HAL_SPI_Init(&hspi1) != HAL_OK) { Error_Handler(); } HAL_SPI_Transmit_IT(&hspi1, tx_buffer, BUFFER_SIZE); // 启动中断传输 while (1) { } } ``` 在此示例中,启动中断传输后,将触发TXE中断并在SPI中断处理函数中发送数据。当所有数据都已发送时,禁用TXE中断并重新启动传输以发送下一组数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值