你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

百度了个GPIO模拟SPI代码,加了自己的理解,求拍砖

[复制链接]
今日头条 提问时间:2016-3-14 17:28 /
初学STM32,非常不好意思,我问的问题可能有些2和有些多,我把网上我搜集到的信息也都写出来了,希望可以一起探讨一下,。。。另外再次感谢热心帮助我的热心网友,我的分数只有这个多可以奖励了,,,,不吝笑纳。。。


网上看了一下,似乎GPIO模拟SPI比GPIO模拟I2C简单一些,
大部分I2C有不少函数封装他的时序,注释都是自带的,没改过,有几个问题想讨论一下
1. SPI一般就两个函数貌似,一个init,一个CPOL和CHPA组合出来的四种时序之一,写出ReadWrite函数,写出来了就可以直接用的样子,请问是这样吗
2. 我还想请问一下请问一下,为什么下面MOSI的脚要用模拟输入?
3. 我还想请问一下,下面的SPIx_FLASH_SendByte中有一句
    {
      GPIO_SetBits(GPIOC, GPIO_Pin_7); //    //SO=1
    }
为什么每次循环都要改变,根据他的初始化,这个是片选的,片选的脚每次都要根据数据改变吗?不是SDO根据数据改变吗?

4.CS和SS是同一根线吗?  我看到网上有描述 SS:片选线,低电平有效,由主机输出,是不是说写0是主机输出,写1是从机输出,要一直改变?

我的思路是这样的,一根MOSI是设置输出,一根MISO设置输入,还有CS和时钟,
1)时钟根据CPOL和CHPA来配置,分别配置为空闲和采样的边沿
2)MOSI每输出一个位,就从MISO接收一个位,配合时钟搞
3)MOSI的时候CS(就是SS)=0,MISO的时候CS(就是SS)=1
4)循环8次以后,发送完也接收完了,就OK了。。
5)也就是一共两个函数,
     一个init,配置输入输出什么的,还有一个是读写同步的一个ReadWrite函数。
5.大致看一下下面的代码的话?  可以照着搞一搞吗?
void SPI_FLASH_Init1(void)//io初始化配置
{

  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE);//初始化A和C的时钟

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_9;//CS片选  CLK时钟,都是输出
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_8 ;//GPIOC_PIN8
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //MOSI用了模拟输入
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;//GPIOA_PIN8
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//MISO
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}
//关键在读取函数
//包括读取和发送
u8 SPIx_FLASH_SendByte(u8 byte)
{
  uint8_t i;
  u8 Temp=0x00;//临时变量
  unsigned char SDI; //输入进来的char
  for (i = 0; i < 8; i++)
  {
    GPIO_SetBits(GPIOC, GPIO_Pin_9);//sclk = 0;//先将时钟拉高
    if (byte&0x80)   //看看最高位是否是1   
    {
      GPIO_SetBits(GPIOC, GPIO_Pin_7); //    //SO=1
    }
    else
    {
      GPIO_ResetBits(GPIOC, GPIO_Pin_7);//     //SO=0
    }
    byte <<= 1;  
    GPIO_ResetBits(GPIOC, GPIO_Pin_9);//    //sclk = 1; 拉低时钟
    SDI = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_8);//判断si是否有输入
    Temp<<=1;

    if(SDI)       //读到1时
    {
      Temp++;  //置1  即向右移动一位同时加1   因上边有<<=1
    }
    GPIO_SetBits(GPIOC, GPIO_Pin_9);//sclk = 0;//   拉高时钟
  }

  return Temp; //返回读到miso输入的值     

}         


收藏 评论7 发布时间:2016-3-14 17:28

举报

7个回答
今日头条 回答时间:2016-3-15 16:19:29
自顶一个,绝不多顶。。
木易-357428 回答时间:2016-3-15 17:38:02
adlu 回答时间:2016-3-15 18:36:51
SPI的时序是很简单,很容易理解的,你把它想的太复杂了。

首先一点,SPIx_FLASH_SendByte()函数并不包含CS引脚的控制。
SO是数据输出引脚。
如果只看输出,函数为
SendByte(byte)
{
for(i=0;i<8;i++){
   if (byte & 0x80) SO = 1;
   else SO = 0;
   SCLK = 0;
   SCLK = 1;
   byte <<= 1;
}
}

其中(byte & 0x80)是取当前的最高bit,要看到后面的移位操作byte <<= 1;
小强1982 回答时间:2016-3-15 23:26:19
mark一下,后面会用到
废鱼 回答时间:2016-3-16 10:39:22
CS是一个片选信号,当一个SPI挂多个设备时,可以通过拉低对应设备的CS来进行数据传输。
yanhaijian 回答时间:2016-3-16 13:01:54
CS是相对于主机而言,SS相对于从机而言,主机的CS脚连接到从机的SS脚,我这样理解应该是正确的吧。
beary 回答时间:2016-3-16 13:15:23
adlu 发表于 2016-3-15 18:36
SPI的时序是很简单,很容易理解的,你把它想的太复杂了。

首先一点,SPIx_FLASH_SendByte()函数并不包含CS ...

正好借楼和楼主的帖子问一下,
你这个byte是不理会receivce的数据,而其实是有数据的吧?

另外麻烦请问一下,SPI是以位为单位全双工的还是字节为单位双工的

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版