SPI多机通信

嵌入式Linux,
嵌入式领域专家
博客专家认证
2013-04-24 04:43:05
我现在想用两台单片机上进行SPI的多机通信,可收发,用到四根线SDO,SDI,EN,SCK、

我是这样进行假设的、

主机发送一个数据的8位、每个时钟上升沿开始发送数据、8个时钟后数据发送完毕

从机的话是如何进行接收的呢?(主机发送的8位数据不可能是全部存在了SDO上面的吧)、那么从机是检测每来一个时钟进行一次数据的存储了吗?那这样的话,从机的sck线是不是要设为输入状态了呢?

感觉发送很容易

void send(unsigned char date)
{
en=1;
_delay(10);
en-0;
sck=0;
for(int i=0;i<8;i++)
{
sdo=date&0x80;
sck=1;
_delay(10);
date<<=1;
sck=0;
}
}


上面是我写帖子时顺手写下的发送函数,要是主机以这样的方式发送出去的话、从机应该如何接收?

了解的人,请帮助帮助、谢谢了
...全文
637 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
嵌入式Linux, 2013-05-15
  • 打赏
  • 举报
回复
引用 18 楼 of123 的回复:
SPOL 是时钟极性模式选择,0 是高电平有效,1 是低电平有效。 SPHA 是时钟相位模式选择,这个要看时序图才能明白。 例如 (SPHA = 1 且 SPOL = 1) 或 (SPHA = 0 且 SPOL = 0)就是时钟上升沿采样。
恩、感谢
of123 2013-05-15
  • 打赏
  • 举报
回复
SPOL 是时钟极性模式选择,0 是高电平有效,1 是低电平有效。 SPHA 是时钟相位模式选择,这个要看时序图才能明白。 例如 (SPHA = 1 且 SPOL = 1) 或 (SPHA = 0 且 SPOL = 0)就是时钟上升沿采样。
嵌入式Linux, 2013-05-13
  • 打赏
  • 举报
回复
引用 16 楼 lxmlcb 的回复:
关于SPI每一个芯片都有自己的定义的,大部分是差不多的,有些时序也和标准的有些差别,所以还是要先弄清楚你使用芯片的datasheet,看看它要求的时序,然后再使用,按照要求完成初始化设置,直接就可以在中断中处理了,记得设置en控制
谢谢这位兄弟
lxmlcb 2013-05-13
  • 打赏
  • 举报
回复
关于SPI每一个芯片都有自己的定义的,大部分是差不多的,有些时序也和标准的有些差别,所以还是要先弄清楚你使用芯片的datasheet,看看它要求的时序,然后再使用,按照要求完成初始化设置,直接就可以在中断中处理了,记得设置en控制
嵌入式Linux, 2013-05-09
  • 打赏
  • 举报
回复
引用 14 楼 of123 的回复:
上面的代码都是用 GPIO 方式软件模拟 SPI 的。从你的叙述来看,如果你看的资料是你的芯片的,那你的芯片是有 SPI 硬件模块的,可以直接使用硬件的 SPI。 一般就是在寄存器中设置主/从、SPHA、SPOL 以及高/低位先发。如果是主,还会需要设置串行时钟频率(一般是分频系数)。仔细看你的 DataSheet。 你现在用 GPIO 方式不成功,可能是你的 SPI 模块的某些引脚(如 SCK)不支持 GPIO 模式操作,或者你没有设置成支持 GPIO。
的确是这样,不过对于SPHA和SPOL是怎么作用的呢?是不是一种模式的选择,还有的是我拿到的资料讲的大多只是API函数,而且是一系列的,并且我在不同的SDK上会有一些差异,搞不定准备叫FAE过来搞搞
of123 2013-05-09
  • 打赏
  • 举报
回复
上面的代码都是用 GPIO 方式软件模拟 SPI 的。从你的叙述来看,如果你看的资料是你的芯片的,那你的芯片是有 SPI 硬件模块的,可以直接使用硬件的 SPI。 一般就是在寄存器中设置主/从、SPHA、SPOL 以及高/低位先发。如果是主,还会需要设置串行时钟频率(一般是分频系数)。仔细看你的 DataSheet。 你现在用 GPIO 方式不成功,可能是你的 SPI 模块的某些引脚(如 SCK)不支持 GPIO 模式操作,或者你没有设置成支持 GPIO。
嵌入式Linux, 2013-05-08
  • 打赏
  • 举报
回复
今天在我的系统上验证了那几个API函数、发关的时候我用示波器去查看,MOSI引脚,发现有输出、这让我感到非常的高兴,然后再用示波器去测了一下SCL引脚,发现SCL引脚竟然是低电平,一点反应都没有,查了一下资料,有些资料上写着,SPI发送的时候应该会进行如下几个步骤、 1、首先初始化一些什么寄存器呀,设置是发送多少位什么的,还有设置是低位先发送还是高位先发送 2、然后把数据填写到发送的buffer里面去 3、发送buffer里面的数据把数据一位一位的移到MOSI上面去、实际上就是一个移位寄存器的原理 4、发送完成 后面我再测了一下EN脚,发现EN脚一直都是高电平、不过这里可以理解,可以理解成高电平使能发送 还有,我用串口打印了一下发送的那个API函数,返回的值是0,说明是这个函数已经成功执行了。 如果是这样的话,那我从机要如何接收呢?主机没有发送时钟信号,没有时钟信号是如何发送的,然后从 机要如何搞,真的是太不可理解了
of123 2013-05-03
  • 打赏
  • 举报
回复
的确,搞反了。 接收时应该首先等待 En 有效: while(en){};
of123 2013-05-02
  • 打赏
  • 举报
回复

void send(unsigned char date)
{
   en=1;
   sck=1;
   _delay(10);
   en=0;
   for(int i=0;i<8;i++)
   {
       sck=0;
       sdo=date&0x80;
       _delay(10);
       sck=1;
       _delay(10);
       date<<=1;
   }
   en=1;
   _delay(10);
}

unsigned char recv()
{
   unsigned char tmp = 0;

   while(!en){};
   for(int i=0;i<8;i++)
   {
      tmp <<= 1;
      while(sck){};
      while(!sck){};
      tmp |= sdi;
   }
   return tmp;
}
许多芯片是有 SPI 接口硬件模块的,那就不必软件模拟了。
嵌入式Linux, 2013-05-02
  • 打赏
  • 举报
回复
引用 10 楼 weiqifa0 的回复:
[quote=引用 9 楼 of123 的回复:]

void send(unsigned char date)
{
   en=1;
   sck=1;
   _delay(10);
   en=0;
   for(int i=0;i<8;i++)
   {
       sck=0;
       sdo=date&0x80;
       _delay(10);
       sck=1;
       _delay(10);
       date<<=1;
   }
   en=1;
   _delay(10);
}

unsigned char recv()
{
   unsigned char tmp = 0;

   while(!en){};
   for(int i=0;i<8;i++)
   {
      tmp <<= 1;
      while(sck){};
      while(!sck){};
      tmp |= sdi;
   }
   return tmp;
}
许多芯片是有 SPI 接口硬件模块的,那就不必软件模拟了。
恩、谢谢你、[/quote] 你这个while(!en)当en是0的时候开始传,你这样的话,好像有问题,因为en是0的时候,你while一直在运行了、
嵌入式Linux, 2013-05-02
  • 打赏
  • 举报
回复
引用 9 楼 of123 的回复:

void send(unsigned char date)
{
   en=1;
   sck=1;
   _delay(10);
   en=0;
   for(int i=0;i<8;i++)
   {
       sck=0;
       sdo=date&0x80;
       _delay(10);
       sck=1;
       _delay(10);
       date<<=1;
   }
   en=1;
   _delay(10);
}

unsigned char recv()
{
   unsigned char tmp = 0;

   while(!en){};
   for(int i=0;i<8;i++)
   {
      tmp <<= 1;
      while(sck){};
      while(!sck){};
      tmp |= sdi;
   }
   return tmp;
}
许多芯片是有 SPI 接口硬件模块的,那就不必软件模拟了。
恩、谢谢你、
嵌入式Linux, 2013-05-01
  • 打赏
  • 举报
回复
引用 6 楼 lbing7 的回复:
[quote=引用 5 楼 quannii 的回复:] 郁闷 最近我准备做一个多机通信,就是单片机通过485进行通信,采用的是半双工方式 spi也是采用半双工方式吗??应为串口有限 现在我们考虑用io口模拟i2c 或者spi方式 但是这个比较麻烦
除非硬件BUG,要不能不用模拟的就不用模拟的 485可以用422或者两路485实现全双工[/quote] 那看看你的单片机有没有I2C或者SPI接口了'''模拟的话全半双工就自己定了
嵌入式Linux, 2013-05-01
  • 打赏
  • 举报
回复
引用 5 楼 quannii 的回复:
郁闷 最近我准备做一个多机通信,就是单片机通过485进行通信,采用的是半双工方式 spi也是采用半双工方式吗??应为串口有限 现在我们考虑用io口模拟i2c 或者spi方式 但是这个比较麻烦
引用 5 楼 quannii 的回复:
郁闷 最近我准备做一个多机通信,就是单片机通过485进行通信,采用的是半双工方式 spi也是采用半双工方式吗??应为串口有限 现在我们考虑用io口模拟i2c 或者spi方式 但是这个比较麻烦
感觉模拟I2C好用'用的Io少
lbing7 2013-04-28
  • 打赏
  • 举报
回复
引用 5 楼 quannii 的回复:
郁闷 最近我准备做一个多机通信,就是单片机通过485进行通信,采用的是半双工方式 spi也是采用半双工方式吗??应为串口有限 现在我们考虑用io口模拟i2c 或者spi方式 但是这个比较麻烦
除非硬件BUG,要不能不用模拟的就不用模拟的 485可以用422或者两路485实现全双工
quannii 2013-04-28
  • 打赏
  • 举报
回复
郁闷 最近我准备做一个多机通信,就是单片机通过485进行通信,采用的是半双工方式 spi也是采用半双工方式吗??应为串口有限 现在我们考虑用io口模拟i2c 或者spi方式 但是这个比较麻烦
嵌入式Linux, 2013-04-24
  • 打赏
  • 举报
回复
引用 1 楼 ymm198606 的回复:
从机在每个时钟接收一个数据位,按照上述程序,为先接高位,再接低位,从机的接收管脚应一直处于接收状态,每隔一个时钟周期接收一位数据;从机的SCK配成输入模式
恩、谢谢
嵌入式Linux, 2013-04-24
  • 打赏
  • 举报
回复
引用 2 楼 lbing7 的回复:
从机的sck线是不是要设为输入状态了呢? 这个问题,你要具体看一下对应芯片的IO结构.不过对于多机通信,我比较倾向于类似IIC那种,采用外部上拉的开漏结构的IO.这样,可以少为输入输出方向纠结 如果自己写从机的话,还真得老实从CLK边缘进行判断(当然,你也可以用外中断或者有捕获模式的定时器来处理)要注意的就是要做好超时处理... 不要等待这个边缘都等死在……
谢谢、看来我得从其他地方入手、因为我的从机是上系统的、我找一下API函数接口试试、 一直用中断判断的话,非常浪费CPU的时间
lbing7 2013-04-24
  • 打赏
  • 举报
回复
从机的sck线是不是要设为输入状态了呢? 这个问题,你要具体看一下对应芯片的IO结构.不过对于多机通信,我比较倾向于类似IIC那种,采用外部上拉的开漏结构的IO.这样,可以少为输入输出方向纠结 如果自己写从机的话,还真得老实从CLK边缘进行判断(当然,你也可以用外中断或者有捕获模式的定时器来处理)要注意的就是要做好超时处理... 不要等待这个边缘都等死在里面
ymm198606 2013-04-24
  • 打赏
  • 举报
回复
从机在每个时钟接收一个数据位,按照上述程序,为先接高位,再接低位,从机的接收管脚应一直处于接收状态,每隔一个时钟周期接收一位数据;从机的SCK配成输入模式

27,373

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧