OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2701|回复: 6

SPI2通信 从机进入接收中断后出不来,且接收速度异常

[复制链接]

17

主题

194

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1049
金钱
1049
注册时间
2016-9-3
在线时间
158 小时
发表于 2018-6-5 10:32:07 | 显示全部楼层 |阅读模式
5金钱
主机:STM32F103R8T6,使用TIM3定时发送数据
程序如下:
void SPI_GPIO_INIT(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
       
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);
}

void SPI2_INIT(void)
{
        SPI_InitTypeDef SPI_InitStructure;
       
        RCC_APB1PeriphClockCmd (RCC_APB1Periph_SPI2,ENABLE);
       
        SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_256;
        SPI_InitStructure.SPI_CPHA=SPI_CPHA_2Edge;
        SPI_InitStructure.SPI_CPOL=SPI_CPOL_High;
        SPI_InitStructure.SPI_CRCPolynomial=7;
        SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;
        SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
        SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;
        SPI_InitStructure.SPI_Mode=SPI_Mode_Master;
        SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;
        SPI_Init(SPI2,&SPI_InitStructure);
       
        SPI_Cmd(SPI2,ENABLE);
       
}


void TIM3_INIT(void)
{
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
       
        TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
        TIM_TimeBaseStructure.TIM_Period=999;
        TIM_TimeBaseStructure.TIM_Prescaler=7199;
        TIM_TimeBaseInit (TIM3,&TIM_TimeBaseStructure);
       
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
       
        TIM_Cmd(TIM3,ENABLE);
}

void NVIC_INIT(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
       
        NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
        NVIC_Init(&NVIC_InitStructure);
}

void TIM3_IRQHandler(void)
{
        if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)
        {
                TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
                SPI_I2S_SendData(SPI2,1);
        }
}

int main(void)
{
        SPI_GPIO_INIT();
        SPI2_INIT();
        TIM3_INIT();
        NVIC_INIT();
        while(1);
}


从机:STM32F103C8T6,开启接收中断,每收到数据就向串口打印字符
程序如下:
void SPI_GPIO_INIT(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
       
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOB,&GPIO_InitStructure);
}


void SPI2_INIT(void)
{
        SPI_InitTypeDef SPI_InitStructure;
       
        RCC_APB1PeriphClockCmd (RCC_APB1Periph_SPI2,ENABLE);
       
        SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_256;
        SPI_InitStructure.SPI_CPHA=SPI_CPHA_2Edge;
        SPI_InitStructure.SPI_CPOL=SPI_CPOL_High;
        SPI_InitStructure.SPI_CRCPolynomial=7;
        SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;
        SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
        SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;
        SPI_InitStructure.SPI_Mode=SPI_Mode_Slave;
        SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;
        SPI_Init(SPI2,&SPI_InitStructure);
        SPI_Cmd(SPI2,ENABLE);
       
        SPI_I2S_ITConfig(SPI2,SPI_I2S_IT_RXNE,ENABLE);  
       
}


void NVIC_INIT(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
       
        NVIC_InitStructure.NVIC_IRQChannel=SPI2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;
        NVIC_Init(&NVIC_InitStructure);
}


void SPI2_IRQHandler(void)                                             
{
        char c[10]={'N','A','M','M','A','E','E','C','H',' '};                                                                       
        int cnt;
        if(SPI_I2S_GetITStatus(SPI2, SPI_I2S_IT_RXNE) == SET)  
{
   SPI_I2S_ClearITPendingBit(SPI2,SPI_I2S_IT_RXNE);  
     for(cnt=0;cnt<10;cnt++)
                {
                  USART_SendData(USART1,c[cnt]);
                  while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);
                }
         
}  
}


void USART_INIT(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
       
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(GPIOA,&GPIO_InitStructure);
       
       
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
        GPIO_Init(GPIOA,&GPIO_InitStructure);
       
        USART_InitStructure.USART_BaudRate=9600;
        USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
        USART_InitStructure.USART_Parity=USART_Parity_No;
        USART_InitStructure.USART_StopBits=USART_StopBits_1;
        USART_InitStructure.USART_WordLength=USART_WordLength_8b;
        USART_Init(USART1,&USART_InitStructure);
       
        USART_Cmd(USART1,ENABLE);
        USART_ClearFlag(USART1,USART_FLAG_TC);
       
}


int main(void)
{
        SPI_GPIO_INIT();
  SPI2_INIT();
  NVIC_INIT();
        USART_INIT();
        while(1);
}




最佳答案

查看完整内容[请看2#楼]

对的, 不好意思,我马虎了;;这个问题找到了解决办法,就是读DR寄存器来清除中断标志。SPI_I2S_ClearITPendingBit(SPI2,SPI_I2S_IT_RXNE);这个函数操作的是SR寄存器,只是清除了状态
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

17

主题

194

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1049
金钱
1049
注册时间
2016-9-3
在线时间
158 小时
 楼主| 发表于 2018-6-5 10:32:08 | 显示全部楼层
szczyb1314 发表于 2018-6-8 08:40
如果是或的话,USART_FLAG_TC一直未被SET,i一直加加,当i>200时USART_FLAG_TC还是RESET,这样子i已经超过 ...

对的, 不好意思,我马虎了;;这个问题找到了解决办法,就是读DR寄存器来清除中断标志。SPI_I2S_ClearITPendingBit(SPI2,SPI_I2S_IT_RXNE);这个函数操作的是SR寄存器,只是清除了状态
回复

使用道具 举报

33

主题

1628

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6677
金钱
6677
注册时间
2015-8-25
在线时间
1036 小时
发表于 2018-6-5 18:33:22 | 显示全部楼层
USART_SendData(USART1,c[cnt]);
                  while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET);不要在这里死等
改下:USART_SendData(USART1,c[cnt]);
                  while((USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)&&(i<=200)){i++}
if(i<=200){表明发送成功}
else{表明发送失败}
如果发送失败,再看看发送失败的原因
He who fights with monsters should look to it that he himself does not become a monster, when you gaze long into the abyss, the abyss also gazes into you.
过于执着就会陷入其中,迷失自己,困住自己。
回复

使用道具 举报

17

主题

194

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1049
金钱
1049
注册时间
2016-9-3
在线时间
158 小时
 楼主| 发表于 2018-6-7 14:35:10 | 显示全部楼层
szczyb1314 发表于 2018-6-5 18:33
USART_SendData(USART1,c[cnt]);
                  while(USART_GetFlagStatus(USART1,USART_FLAG_TC)==R ...

i<=200是在干嘛?为什么要这样呢?
回复

使用道具 举报

33

主题

1628

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6677
金钱
6677
注册时间
2015-8-25
在线时间
1036 小时
发表于 2018-6-7 14:45:23 | 显示全部楼层

给一个等待时间,
while((USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)&&(i<=200)){i++}
整个这句话的意思是,我在i从0加到200的这段时间内等待串口的发送完成,如果i++超过了200就退出了死循环,这时认为是发送失败了,如果你的串口在i<200的某个时候发送成功了,也会退出死循环,这时肯定是发送成功了才退出的。这样子做的好处是避免我的程序在while里面死等不跳出(死等不跳出是指串口发送出了问题一直无法将USART_FLAG_TC置位,这个时候你的程序会卡死在死循环里,后面的程序无法执行,更有可能发生事故)。
He who fights with monsters should look to it that he himself does not become a monster, when you gaze long into the abyss, the abyss also gazes into you.
过于执着就会陷入其中,迷失自己,困住自己。
回复

使用道具 举报

17

主题

194

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1049
金钱
1049
注册时间
2016-9-3
在线时间
158 小时
 楼主| 发表于 2018-6-7 15:11:29 | 显示全部楼层
szczyb1314 发表于 2018-6-7 14:45
给一个等待时间,
while((USART_GetFlagStatus(USART1,USART_FLAG_TC)==RESET)&&(i

谢谢,我懂你意思了,但是这样不是应该用“||”运算吗?
回复

使用道具 举报

33

主题

1628

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6677
金钱
6677
注册时间
2015-8-25
在线时间
1036 小时
发表于 2018-6-8 08:40:01 | 显示全部楼层
午夜狼嚎 发表于 2018-6-7 15:11
谢谢,我懂你意思了,但是这样不是应该用“||”运算吗?

如果是或的话,USART_FLAG_TC一直未被SET,i一直加加,当i>200时USART_FLAG_TC还是RESET,这样子i已经超过200但是while的条件还是true,还是无法退出死循环的,失去了等待i加到200的意义,不是吗?另外这个200是自己根据情况估算的,不一定要这个值,具体情况具体对待
He who fights with monsters should look to it that he himself does not become a monster, when you gaze long into the abyss, the abyss also gazes into you.
过于执着就会陷入其中,迷失自己,困住自己。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-29 10:40

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表