OpenEdv-开源电子网

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

模拟SPI通信从机接收的时候一般用什么方法

[复制链接]

34

主题

252

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
473
金钱
473
注册时间
2020-5-11
在线时间
217 小时
发表于 2020-11-4 16:20:43 | 显示全部楼层 |阅读模式
20金钱
最近有模拟SPI 的需求,但是现在被困在了从机接收上,从机接收上主要一般思路应该是两种方法1.轮询   2.中断   两种方式我都试了。现主要问题有如下:
我的主从机之间的连接只用了三个线,因为没有片选的需要所以去除了CS (其实也是因为引脚不够用),现在只有MOSI  MISO CLK,连接方式如下

                                              主                               从

                                            CLK   ------------->   CLK

                                           MOSI ------------->   MOSI

                                           MISO ------------->   MISO                        

  • 对于轮询方式,最大的困难是在线有限的情况下,当主机准备发送,从机不知道什么时候接收,这里不用考虑从机返回,所以采用半双工。
               我的做法是初始状态让CLK和MOSI都为低电平,当主机发送的时候CLK保持低电平  ,拉高MOSI,并且保持这个状态3ms。这么做的原因是我采用SPI是上升沿发送,下降沿接收,在正常情况下MOSI为高电平的时候,CLK不可能保持3ms的低电平。
               主机发送如下
  1. void SPI_Send_Byte(u8 data)
  2. {
  3.     u8 i;
  4.     for(i = 0; i < 8; i++)
  5.     {
  6.         SPI_CLK(0);
  7.         SPI_DELAY();
  8.         if(data & 0x80)
  9.         {
  10.             SPI_MOSI(1);
  11.         }
  12.         else
  13.         {
  14.             SPI_MOSI(0);
  15.         }
  16.         data <<= 1;
  17.         SPI_CLK(1);
  18.         delay_us(50);
  19.     }           
  20. }
复制代码
       从机接收如下
  1. u8 SPI_Receive_Byte(void)
  2. {
  3.     u8 i,j,data=0;
  4.     delay_us(50);
  5.     for(i = 0,j=0; i < 8; i++)
  6.     {
  7.         delay_us(40);
  8.         if(SPI_MOSI_PIN==1)
  9.         {
  10.             data |= (1<<(7-i));
  11.         }
  12.         delay_us(60);
  13.     }
  14.     return data;
  15. }
复制代码
现在的问题就是从机接收发送无规律性的错误,检查过CLK和MOSI的波形,都是正确的

           2. 中断接收
            中断的话,老是进不去
  1. void EXTIX_Init(void)
  2. {

  3.            EXTI_InitTypeDef EXTI_InitStructure;
  4.     NVIC_InitTypeDef NVIC_InitStructure;
  5.     SPI_CLK_Init();
  6.           RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);        //使能复用功能时钟


  7.           GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource6);
  8.           EXTI_InitStructure.EXTI_Line=EXTI_Line6;
  9.           EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  10.           EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  11.           EXTI_Init(&EXTI_InitStructure);                  //根据EXTI_InitStruct中指定的参数初始化外设EXTI寄存器


  12.           NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;                        //使能按键KEY0所在的外部中断通道
  13.           NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;        //抢占优先级2
  14.           NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;                                        //子优先级0
  15.           NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                //使能外部中断通道
  16.           NVIC_Init(&NVIC_InitStructure);            //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器

  17. }


  18. u8 SPI_Buffer_RX[16]={0};
  19. u8 SPI_Buffer_TX[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
  20. u8 i=0;
  21. u8 j=0;
  22. u16 rise=0;
  23. u16 fall=0;

  24. //外部中断6服务函数
  25. void EXTI9_5_IRQHandler(void)
  26. {
  27.     delay_us(5);
  28.         if(SPI_CLK_PIN)                //上升沿,接收数据
  29.         {
  30.             port4=0;
  31.                 i=rise/8;

  32.                 if(SPI_MOSI_PIN)                 //比如说传输过来的数为1100 1010 ,高位在前
  33.                 {
  34.                         //SPI_Buffer_RX[i] |= 0x01;
  35.                         SPI_Buffer_RX[i] |= 1<<(7-(rise%8));
  36.                 }
  37.                 //SPI_Buffer_RX[i] <<= (rise%8);
  38.         rise++;
  39.         }
  40.         EXTI_ClearITPendingBit(EXTI_Line6); //清除LINE6上的中断标志位
  41. }
复制代码

想问问大家有没有这方面的经验。。。







最佳答案

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

新建一次工程之后,中断的方法可以了
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

34

主题

252

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
473
金钱
473
注册时间
2020-5-11
在线时间
217 小时
 楼主| 发表于 2020-11-4 16:20:44 | 显示全部楼层
新建一次工程之后,中断的方法可以了
回复

使用道具 举报

12

主题

3402

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8686
金钱
8686
注册时间
2020-5-11
在线时间
4168 小时
发表于 2020-11-4 16:45:05 | 显示全部楼层
SPI_Receive_Byte没有等待SCK的边沿啊?
难道是想弄成像USART那样?
数据一多波特率误差累积起来就严重了.
专治疑难杂症
回复

使用道具 举报

34

主题

252

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
473
金钱
473
注册时间
2020-5-11
在线时间
217 小时
 楼主| 发表于 2020-11-4 16:50:52 | 显示全部楼层
LcwSwust 发表于 2020-11-4 16:45
SPI_Receive_Byte没有等待SCK的边沿啊?
难道是想弄成像USART那样?
数据一多波特率误差累积起来就严重了.
...

我用示波器读后面的波形的时候发现了这个问题,所以要保证数据不过长,但是现在数据接收也有问题,读到的数据毫无规律性
回复

使用道具 举报

34

主题

252

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
473
金钱
473
注册时间
2020-5-11
在线时间
217 小时
 楼主| 发表于 2020-11-4 16:52:32 | 显示全部楼层
LcwSwust 发表于 2020-11-4 16:45
SPI_Receive_Byte没有等待SCK的边沿啊?
难道是想弄成像USART那样?
数据一多波特率误差累积起来就严重了.
...

比较偏向于用中断,但是进不去啊,单纯用按键测试中断程序的话没有问题,读CLK上升沿就有问题了
回复

使用道具 举报

12

主题

3402

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8686
金钱
8686
注册时间
2020-5-11
在线时间
4168 小时
发表于 2020-11-4 16:58:21 | 显示全部楼层
asshole 发表于 2020-11-4 16:52
比较偏向于用中断,但是进不去啊,单纯用按键测试中断程序的话没有问题,读CLK上升沿就有问题了

中断里不要有延时,先用低波特率试一下.
专治疑难杂症
回复

使用道具 举报

34

主题

252

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
473
金钱
473
注册时间
2020-5-11
在线时间
217 小时
 楼主| 发表于 2020-11-4 17:00:55 | 显示全部楼层
LcwSwust 发表于 2020-11-4 16:58
中断里不要有延时,先用低波特率试一下.

100us一次触发,应该不影响的
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-6-21 16:15

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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