软件模拟SPI接口程序代码(4种模式)

软件模拟SPI接口程序代码(4种模式)

初始化代码

/**SPI1 GPIO Configuration    
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI 
    */
#define SPI_SCK_PIN                     GPIO_PIN_5
#define SPI_SCK_GPIO_PORT               GPIOA
#define SPI_MOSI_PIN                    GPIO_PIN_7
#define SPI_MOSI_GPIO_PORT              GPIOA
#define SPI_MISO_PIN                    GPIO_PIN_6
#define SPI_MISO_GPIO_PORT              GPIOA
#define SPI_NSS_PIN                     GPIO_PIN_14
#define SPI_NSS_GPIO_PORT               GPIOD
 
 
#define SPI_SCK_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOA_CLK_ENABLE()
#define SPI_MISO_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()
#define SPI_MOSI_GPIO_CLK_ENABLE()      __HAL_RCC_GPIOA_CLK_ENABLE()
#define SPI_NSS_GPIO_CLK_ENABLE()       __HAL_RCC_GPIOD_CLK_ENABLE()
 
#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) 
	·
 
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();
 
 
  /*##-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);
  
}

模拟spi 4种工作模式

/* CPOL = 0, CPHA = 0, MSB first */
uint8_t SOFT_SPI_RW_MODE0( uint8_t write_dat )
{
    uint8_t i, read_dat;
    for( i = 0; i < 8; i++ )
    {
        if( write_dat & 0x80 )
            MOSI_H;  
        else                    
            MOSI_L;  
        write_dat <<= 1;
        delay_us(1);	
        SCK_H; 
        read_dat <<= 1;  
        if( MISO ) 
            read_dat++; 
		delay_us(1);
        SCK_L; 
        __nop();
    }
	
    return read_dat;
}
 
 
/* CPOL=0,CPHA=1, MSB first */
uint8_t SOFT_SPI_RW_MODE1(uint8_t byte) 
{
    uint8_t i,Temp=0;
 
	for(i=0;i<8;i++)     // 循环8次
	{
		SCK_H;     //拉高时钟
		if(byte&0x80)
        {
			MOSI_H;  //若最到位为高,则输出高
        }
		else      
		{
			MOSI_L;   //若最到位为低,则输出低
		}
		byte <<= 1;     // 低一位移位到最高位
		delay_us(1);
		SCK_L;     //拉低时钟
		Temp <<= 1;     //数据左移
 
		if(MISO)
			Temp++;     //若从从机接收到高电平,数据自加一
		delay_us(1);
 
	}
	return (Temp);     //返回数据
}
 
/* CPOL=1,CPHA=0, MSB first */
uint8_t SOFT_SPI_RW_MODE2(uint8_t byte) 
{
    uint8_t i,Temp=0;
 
	for(i=0;i<8;i++)     // 循环8次
	{
		if(byte&0x80)
        {
			MOSI_H;  //若最到位为高,则输出高
        }
		else      
		{
			MOSI_L;   //若最到位为低,则输出低
		}
		byte <<= 1;     // 低一位移位到最高位
		delay_us(1);
		SCK_L;     //拉低时钟
		Temp <<= 1;     //数据左移
 
		if(MISO)
			Temp++;     //若从从机接收到高电平,数据自加一
		delay_us(1);
		SCK_H;     //拉高时钟
		
	}
	return (Temp);     //返回数据
}
 
 
/* CPOL = 1, CPHA = 1, MSB first */
uint8_t SOFT_SPI_RW_MODE3( uint8_t write_dat )
{
    uint8_t i, read_dat;
    for( i = 0; i < 8; i++ )
    {
		SCK_L; 
        if( write_dat & 0x80 )
            MOSI_H;  
        else                    
            MOSI_L;  
        write_dat <<= 1;
        delay_us(1);	
        SCK_H; 
        read_dat <<= 1;  
        if( MISO ) 
            read_dat++; 
		delay_us(1);
        __nop();
    }
    return read_dat;
}
 

CPOL = 0, CPHA = 0, MSB first 模式下读写多字节数据

/*
u16Len: 读写的数据长度
pu8Dat  写入的数据
pu8RxBuf 读取的数据
*/
int soft_spi_trx_bytes ( uint16_t u16Len, uint8_t* pu8Dat, uint8_t* pu8RxBuf)
{
    uint16_t i = 0; 
	
    if (( NULL == pu8Dat ) || ( 0 == u16Len ))
    {
        return 1;
    }
    
    for ( i = 0; i < u16Len; i++ )
    {
       pu8RxBuf[i]=SOFT_SPI_RW_MODE0 ( pu8Dat[i]);
    }
    return 0;
}
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用Arduino模拟SPI接口驱动OLED屏,需要进行以下步骤: 1. 首先,将OLED屏的引脚连接到Arduino的相应引脚。通常,OLED屏使用的是SPI接口,因此需要连接ARDUINO的 MOSI、MISO、CLK、CS、DC、RESET引脚。 2. 接下来,在Arduino IDE中导入OLED屏的库文件。可以在网上搜索“Arduino OLED Library”,然后下载并安装。 3. 在Arduino IDE中打开一个新的空白项目,然后在程序中包含所需的库文件。 4. 设置SPI通信参数,包括时钟频率、数据位顺序、数据传输模式等。 5. 初始化OLED屏的引脚,并设置其分辨率和显示模式。 6. 使用库函数向OLED屏发送图像和文本等数据,以显示所需信息。 下面是一个示例程序,演示如何使用Arduino模拟SPI接口驱动OLED屏: ``` #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #define OLED_MOSI 9 #define OLED_CLK 10 #define OLED_DC 11 #define OLED_CS 12 #define OLED_RESET 13 Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); void setup() { display.begin(SSD1306_SWITCHCAPVCC); display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0,0); display.print("Hello, world!"); display.display(); } void loop() { } ``` 这个程序使用了Adafruit_SSD1306库来驱动OLED屏,通过设置屏幕分辨率和显示模式,向屏幕上显示了“Hello, world!”这个文本。你可以参考这个程序,编写自己的代码来驱动OLED屏。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值