1.15 SPI数码管实验

一.SPI总线

SPI是全双工三/四总线制串行总线,支持多主机多从机模式,常用单主机多从机模式
数据传输可以先传输高位也可以先传输低位。

四线(单主机多从机):    
    MOSI:主机输出,从机输入
    MISO:主机输入,从机输出
    SCLK:   时钟信号
    /SS:片选线,从器件使能信号
三线:(单主机单从机)
    MOSI:主机输出,从机输入
    MISO:主机输入,从机输出
    SCLK:   时钟信号

IIC和SPI的异同点

相同点:1.都采用同步串行总线的通信方式

               2.都采用主从模式

不同点:1.IIC总线采用半双工通信方式,SPI采用全双工通信方式

               2.IIC有应答机制,SPI没有应答机制

               3.IIC通过总线寻找从机,SPI通过片选线寻找从机

               4.IICSCL高电平读数据,低电平写数据

                SPI边缘采样,边缘触发

二.通信协议

通信协议
边缘触发,边缘采样
时钟极性    0:SCL空闲状态为低电平       1:SCL空闲状态为高电平
时钟相位      0:MOSI MISO 在奇数边采样        1:MOSI MISO 在偶数边采样

起始信号: NSS信号线由高变低,是SPI通讯的起始信号

结束信号:NSS信号由低变高,是SPI通讯的停止信号

数据传输:SPI使用MOSI及MISO信号线来传输数据,使用SCK信号线进行数据同步。 MOSI及MISO数据线在SCK的每个时钟周期传输一位数据,且数据输入输出是同时进行 的。SPI每次数据传输可以 8 位或 16 位为单位,每次传输的单位数不受限制

三.M74HC595芯片

工作原理:

        

 1.分析引脚作用

 

2.分析真值表

 四.代码

spi.c

#include "spi.h"
/* SPI4_NSS 	---->   PE11
 * SPI4_SCK     ---->   PE12
 * SPI4_MOSI    ---->   PE14
 * SPI4_MISO    ---->   PE13
 * */
 
/* 数码管的编码, 先发送低位,在发送高位
 * A B C D E F G DP
 * 1 1 1 1 1 1 0 0    0xFC   0
 * 0 1 1 0 0 0 0 0    0x60   1
 * 1 1 0 1 1 0 1 0    0xDA   2
 * 1 1 1 1 0 0 1 0    0xF2   3
 * 0 1 1 0 0 1 1 0    0x66   4
 * 1 0 1 1 0 1 1 0    0xB6   5 
 * 1 0 1 1 1 1 1 0    0xBE   6
 * 1 1 1 0 0 0 0 0    0xE0   7
 * 1 1 1 1 1 1 1 0    0xFE   8
 * 1 1 1 1 0 1 1 0    0xF6   9
 * */
void delay_us1(unsigned int us)
{
	int i,j;
	for(i = 0; i < us;i++)
		for (j = 0; j < 1;j++);
}
 
void SPI_init(void)
{
	RCC->MP_AHB4ENSETR |= (0x1 << 4);
	// MOSI    PE14 
	GPIOE->MODER &= (~(0x3 << 28));
	GPIOE->MODER |= (0x1 << 28);
	GPIOE->OTYPER &= (~(0x1 << 14));
	GPIOE->OSPEEDR &= (~(0x3 << 28));
	GPIOE->PUPDR &= (~(0x3 << 28));
	// MISO    PE13
	GPIOE->MODER &= (~(0x3 << 26));
	GPIOE->OSPEEDR &= (~(0x3 << 26));
	GPIOE->PUPDR &= (~(0x3 << 26));
	// SCK     PE12	
	GPIOE->MODER &= (~(0x3 << 24));
	GPIOE->MODER |= (0x1 << 24);
	GPIOE->OTYPER &= (~(0x1 << 12));
	GPIOE->OSPEEDR &= (~(0x3 << 24));
	GPIOE->PUPDR &= (~(0x3 << 24));
	// NSS     PE11
	GPIOE->MODER &= (~(0x3 << 22));
	GPIOE->MODER |= (0x1 << 22);
	GPIOE->OTYPER &= (~(0x1 << 11));
	GPIOE->OSPEEDR &= (~(0x3 << 22));
	GPIOE->PUPDR &= (~(0x3 << 22));
	NSS_OUTPUT_L();    // 595芯片的锁存引脚拉低
	SCK_OUTPUT_L();    // SPI的时钟线拉低
}
 
void SPI_write(unsigned char dat)
{
	//for循环
	//if判断条件,先发送低位
	//if成立MOSI线写高
	//else MOSI线写低
	//移位寄存器时钟从低到高的变化
	
	for( unsigned char i=0;i<8;i++){		
		delay_us1(100);
		if(dat & 0x01){	  //从低位到高位发送,从低位开始判断
			MOSI_OUTPUT_H();	1---写高电平
		}else{		
			MOSI_OUTPUT_L();    0----写低电平
		}
		SCK_OUTPUT_L();    //根据真值表,移位寄存器存储L,H,移位时钟寄存器需要由低电平到高电平
		delay_us1(100);
		SCK_OUTPUT_H();
		delay_us1(100);
 
		dat>>=1;
	}
}

main.c

#include "spi.h"
extern void printf(const char *fmt, ...);
void delay_ms(int ms)
{
	int i,j;
	for(i = 0; i < ms;i++)
		for (j = 0; j < 1800; j++);
}
 
 
 
int num[10] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6};
 
int main(void){
	//for循环条件
	//内容:先发送位,在发送段
	//0xF0 num[i]
	SPI_init();
while(1){
		
	for(int i=0;i<4;i++){
		
		
		//SPI_write(0xF0);
		SPI_write(0x80>>i);    //发送位
		SPI_write(num[i+1]);   //发送段
		NSS_OUTPUT_L();      //根据真值表,移位寄存器中数据锁存到锁存寄存器中,锁存时钟寄存器需要由低电平到高电平
		delay_ms(100);
		NSS_OUTPUT_H();
		delay_ms(100);
 
	}
}
	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值