打印
[应用相关]

stm32 软件模拟SPI代码

[复制链接]
6439|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hanzhen654|  楼主 | 2018-8-24 13:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
自己画了一块stm32的板子,因为spi没用接到固定的引脚上面不得不用这种方式。
引脚定义:
#define SPI_SCK_PIN                     GPIO_PIN_4
#define SPI_SCK_GPIO_PORT               GPIOC
#define SPI_MOSI_PIN                    GPIO_PIN_7
#define SPI_MOSI_GPIO_PORT              GPIOC
#define SPI_MISO_PIN                    GPIO_PIN_8
#define SPI_MISO_GPIO_PORT              GPIOC
#define SPI_NSS_PIN                     GPIO_PIN_6
#define SPI_NSS_GPIO_PORT               GPIOC
#define SPI_RESET_PIN                   GPIO_PIN_5
#define SPI_RESET_GPIO_PORT             GPIOC


沙发
hanzhen654|  楼主 | 2018-8-24 13:53 | 只看该作者
定义时钟使能
#define SPI_SCK_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOC_CLK_ENABLE()
#define SPI_MISO_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOC_CLK_ENABLE()
#define SPI_MOSI_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOC_CLK_ENABLE()
#define SPI_NSS_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOC_CLK_ENABLE()
#define SPI_RESET_GPIO_CLK_ENABLE()     __HAL_RCC_GPIOC_CLK_ENABLE()


使用特权

评论回复
板凳
hanzhen654|  楼主 | 2018-8-24 13:55 | 只看该作者
定义片选高低信号,类似sys.h
#define MOSI_H  HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_SET)  
#define MOSI_L  HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_RESET)  
#define SCK_H   HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_SET)  
#define SCK_L   HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_RESET)  
#define MISO    HAL_GPIO_ReadPin(SPI_MISO_GPIO_PORT, SPI_MISO_PIN)
#define NSS_H   HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_SET)  
#define NSS_L   HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_RESET)


使用特权

评论回复
地板
hanzhen654|  楼主 | 2018-8-24 13:56 | 只看该作者
定义相关EEPROM地址
#define EEPROM_DAC_START_ADDR   DATA_EEPROM_BASE+6             /* Start [url=home.php?mod=space&uid=72445]@[/url] of user EEPROM area */
#define EEPROM_DAC_END_ADDR     (EEPROM_BIAS_START_ADDR + 16)   /* End @ of user EEPROM area */
#define IS_DAC_DATA_ADDRESS(__ADDRESS__)          (((__ADDRESS__) >= EEPROM_DAC_START_ADDR) && ((__ADDRESS__) <= EEPROM_DAC_END_ADDR))
#define IS_DAC_CH_ADDRESS(__ADDRESS__)          (((__ADDRESS__) >= 1) && ((__ADDRESS__) <= 4))


使用特权

评论回复
5
hanzhen654|  楼主 | 2018-8-24 13:57 | 只看该作者
函数声明,包括SPI初始化,SPI读写函数
void SPI_Init(void);
uint16_t SPI_ReadWrite_Byte(uint8_t cmd_addr, uint16_t data);


使用特权

评论回复
6
hanzhen654|  楼主 | 2018-8-24 14:01 | 只看该作者
SPI初始化
void SPI_Init(void)
{  
  /*##-1- Enable peripherals and GPIO Clocks #################################*/
  /* Enable GPIO TX/RX clock */
  SPI_SCK_GPIO_CLK_ENABLE();
  SPI_MISO_GPIO_CLK_ENABLE();
  SPI_MOSI_GPIO_CLK_ENABLE();
  SPI_NSS_GPIO_CLK_ENABLE();
  SPI_RESET_GPIO_CLK_ENABLE();

  /*##-2- Configure peripheral GPIO ##########################################*/
  /* SPI SCK GPIO pin configuration  */
  GPIO_InitTypeDef GPIO_InitStruct;
  
  GPIO_InitStruct.Pin       = SPI_SCK_PIN;
  GPIO_InitStruct.Mode      = GPIO_MODE_OUTPUT_PP;
  //GPIO_InitStruct.Pull      = GPIO_PULLDOWN;
  GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_VERY_HIGH;
  HAL_GPIO_Init(SPI_SCK_GPIO_PORT, &GPIO_InitStruct);
  HAL_GPIO_WritePin(SPI_SCK_GPIO_PORT, SPI_SCK_PIN, GPIO_PIN_SET);

  /* SPI MISO GPIO pin configuration  */
  GPIO_InitStruct.Pin = SPI_MISO_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  HAL_GPIO_Init(SPI_MISO_GPIO_PORT, &GPIO_InitStruct);

  /* SPI MOSI GPIO pin configuration  */
  GPIO_InitStruct.Pin = SPI_MOSI_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  HAL_GPIO_Init(SPI_MOSI_GPIO_PORT, &GPIO_InitStruct);
  HAL_GPIO_WritePin(SPI_MOSI_GPIO_PORT, SPI_MOSI_PIN, GPIO_PIN_SET);
  
  GPIO_InitStruct.Pin = SPI_NSS_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  HAL_GPIO_Init(SPI_NSS_GPIO_PORT, &GPIO_InitStruct);
  HAL_GPIO_WritePin(SPI_NSS_GPIO_PORT, SPI_NSS_PIN, GPIO_PIN_SET);
  
  GPIO_InitStruct.Pin = SPI_RESET_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  HAL_GPIO_Init(SPI_RESET_GPIO_PORT, &GPIO_InitStruct);
  HAL_GPIO_WritePin(SPI_RESET_GPIO_PORT, SPI_RESET_PIN, GPIO_PIN_SET);
}


使用特权

评论回复
7
hanzhen654|  楼主 | 2018-8-24 14:02 | 只看该作者
SPI读写函数
uint16_t SPI_ReadWrite_Byte(uint8_t cmd_addr, uint16_t data)
{  
  uint16_t temp=0;
  SPI_Init();
  NSS_L;  
  SCK_H;   
  __NOP();             /*读取第一bit数据 等待数据稳定 根据实际时钟调整*/
  for(uint8_t i=0;i<8;i++)
  {   
    if(cmd_addr&0x80)
    {
      MOSI_H;          /*若最高位为高,则输出高*/
    }
    else
    {
      MOSI_L;          /*若最高位为低,则输出低*/   
    }   
    __NOP();
    cmd_addr <<= 1;
    SCK_L;
    temp <<= 1;        /*数据左移*/
    if(MISO)
    {
      temp++;          /*若从从机接收到高电平,数据自加一*/
    }
    SCK_H;
  }
   
  data <<= 6;
  
  for(uint8_t i=0;i<16;i++)
  {   
    if(data&0x8000)
    {
      MOSI_H;          /*若最高位为高,则输出高*/
    }
    else
    {
      MOSI_L;          /*若最高位为低,则输出低*/   
    }   
    __NOP();
    data <<= 1;
    SCK_L;
    temp <<= 1;        /*数据左移*/
    if(MISO)
    {
      temp++;          /*若从从机接收到高电平,数据自加一*/
    }
    SCK_H;
  }
  NSS_H;
  MOSI_H;
  return temp;
}


使用特权

评论回复
8
hanzhen654|  楼主 | 2018-8-24 14:03 | 只看该作者
大家可以通过基于SPI的传感器来测试,例如nrf24l01等。

使用特权

评论回复
评论
ningxiaoyaoli 2020-5-19 23:26 回复TA
data <<= 6; data为什么要左移6位呢? 
9
zhuotuzi| | 2018-8-24 16:34 | 只看该作者
SPI是最好用IO模拟的串行通信协议。

使用特权

评论回复
10
stm32jy| | 2018-8-24 18:25 | 只看该作者
我一般用的是硬件SPI ,模拟的没怎么写过,

使用特权

评论回复
11
mintspring| | 2018-8-24 23:54 | 只看该作者
IO模拟的其实用的很多的。

使用特权

评论回复
12
guanjiaer| | 2018-9-7 09:53 | 只看该作者
hanzhen654 发表于 2018-8-24 13:56
定义相关EEPROM地址

这个跟eeprom有什么关系呢

使用特权

评论回复
13
guanjiaer| | 2018-9-7 10:04 | 只看该作者
hanzhen654 发表于 2018-8-24 13:56
定义相关EEPROM地址

这个跟eeprom有什么关系呢

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

73

主题

1766

帖子

2

粉丝