作业题目
ARM-SPI实验
作业内容
一、什么是SPI 1.SPI总线是Motorola首先提出的全双工三线/四线同步串行总线 2.采用主从模式(Master Slave)架构;支持多slave模式应用,一般仅支持单Master,多从机 3.时钟由Master控制,在时钟移位脉 冲下,数据按位传输,高位在前,低位在后(MSB first) 4.SPI接口有2根单向数据线,为全双工 通信,目前应用中的数据速率可达几Mbps的水平 5.SPI总线被广泛地使用在FLASH、ADC、LCD等设备与MCU间,要求通讯速率较高的场合 6.SPI接口共有4根信号线, 分别是:设备选择线(片选线):NSS nsc 时钟线:SCK CLK 串行输出数据线:MOSI 串行输入数据线:MISO M:master主机 O:output输出 S:slave从机 I:input输入 7.信号线的作用: ? (1)MOSI:主器件数据输出,从器件数据输入 ? (2)MISO:主器件数据输入,从器件数据输出 ? (3)SCLK :时钟信号,由主器件产生 ? (4)/SS:从器件使能信号,由主器件控制(片选) 二、SPI总线的通信协议 三、SPI总线框图 四、SPI总线的工作原理 五、代码部分 spi.h
#ifndef __SPI_H__
#define __SPI_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
#define MOSI_OUTPUT_H() do{GPIOE->ODR |= (0x1 << 14);}while(0)
#define MOSI_OUTPUT_L() do{GPIOE->ODR &= (~(0x1 << 14));}while(0)
#define NSS_OUTPUT_H() do{GPIOE->ODR |= (0x1 << 11);}while(0)
#define NSS_OUTPUT_L() do{GPIOE->ODR &= (~(0x1 << 11));}while(0)
#define SCK_OUTPUT_H() do{GPIOE->ODR |= (0x1 << 12);}while(0)
#define SCK_OUTPUT_L() do{GPIOE->ODR &= (~(0x1 << 12));}while(0)
void SPI_init(void);
void SPI_write(unsigned char dat);
#endif
spi.c
#include "spi.h"
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);
GPIOE->MODER &= (~(0x3 << 28));
GPIOE->MODER |= (0x1 << 28);
GPIOE->OTYPER &= (~(0x1 << 14));
GPIOE->OSPEEDR &= (~(0x3 << 28));
GPIOE->PUPDR &= (~(0x3 << 28));
GPIOE->MODER &= (~(0x3 << 26));
GPIOE->OSPEEDR &= (~(0x3 << 26));
GPIOE->PUPDR &= (~(0x3 << 26));
GPIOE->MODER &= (~(0x3 << 24));
GPIOE->MODER |= (0x1 << 24);
GPIOE->OTYPER &= (~(0x1 << 12));
GPIOE->OSPEEDR &= (~(0x3 << 24));
GPIOE->PUPDR &= (~(0x3 << 24));
GPIOE->MODER &= (~(0x3 << 22));
GPIOE->MODER |= (0x1 << 22);
GPIOE->OTYPER &= (~(0x1 << 11));
GPIOE->OSPEEDR &= (~(0x3 << 22));
GPIOE->PUPDR &= (~(0x3 << 22));
NSS_OUTPUT_L();
SCK_OUTPUT_L();
}
void SPI_write(unsigned char dat)
{
unsigned char i;
for(i = 0; i < 8; i++)
{
if(dat & 0x01)
{
MOSI_OUTPUT_H();
} else {
MOSI_OUTPUT_L();
}
dat >>= 1;
SCK_OUTPUT_L();
delay_us1(10);
SCK_OUTPUT_H();
delay_us1(10);
}
}
main.c
#include "gpio.h"
#include "uart4.h"
#include "command.h"
#include "beep.h"
#include "key-TI.h"
#include "si7006.h"
#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++);
}
void led_init(void)
{
RCC_MP_AHB4ENSETR |= (0x3 << 4);
gpio_init_t gpio_init = {
.mode = GPIO_OUTPUT,
.type = GPIO_PP,
.speed = LOW_SPEED,
.pupd = NOPUPD,
};
hal_gpio_init(GPIOE, &gpio_init, GPIO_PIN_10);
hal_gpio_init(GPIOF, &gpio_init, GPIO_PIN_10);
hal_gpio_init(GPIOE, &gpio_init, GPIO_PIN_8);
}
void led_flash(void)
{
hal_gpio_write(GPIOE, GPIO_PIN_10, GPIO_SET);
delay_ms(500);
hal_gpio_write(GPIOE, GPIO_PIN_10, GPIO_RESET);
delay_ms(500);
}
int num[10] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6};
int main(void)
{
unsigned char i;
SPI_init();
while(1)
{
#if 1
for(i = 0; i < 10; i++)
{
SPI_write(0xF0);
SPI_write(num[i]);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H();
delay_ms(1000);
}
#else
for(i = 0; i < 4; i++)
{
SPI_write(0x80 >> i);
SPI_write(num[i+1]);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H();
}
#endif
}
return 0;
}
|