令数码管每一位数字不同
利用余晖效应
实现数字从0开始递增和进位
spi.c
#include "spi.h"
void delay_us(unsigned int us)
{
int i,j;
for(i = 0;i<us;i++)
{
for(j=0;j<1;j++);
}
}
void SPI_init(void)
{
//使能GPIOE时钟
RCC->MP_AHB4ENSETR |= (0x1 << 4);
//MOSI管脚PE14,设置输出的属性
GPIOE->MODER &= (~(0x03 << 28));
GPIOE->MODER |= (0x01 <<28);
GPIOE->OTYPER &= (~(0x01 << 14));
GPIOE->OSPEEDR &= (~(0x03 << 28));
GPIOE->PUPDR &= (~(0x03 << 28));
//MISO管脚PE13,设置输入的属性
GPIOE->MODER &= (~(0x03<<26));
GPIOE->OSPEEDR &= (~(0x03 <<26));
GPIOE->PUPDR &= (~(0x03 << 26));
//SCK管脚PE12,设置输出的属性
GPIOE->MODER &= (~(0x03 << 24));
GPIOE->MODER |= (0x01 <<24);
GPIOE->OTYPER &= (~(0x01 << 12));
GPIOE->OSPEEDR &= (~(0x03 << 24));
GPIOE->PUPDR &= (~(0x03 << 24));
//RCK(NSS)管脚,设置输出的属性
//默认PE12和PE11输出低电平,方便产生上升沿
GPIOE->MODER &= (~(0x03 << 22));
GPIOE->MODER |= (0x01 <<22);
GPIOE->OTYPER &= (~(0x01 << 11));
GPIOE->OSPEEDR &= (~(0x03 << 22));
GPIOE->PUPDR &= (~(0x03 << 22));
NSS_OUTPUT_L();
SCK_OUTPUT_L();
}
void SPI_write(unsigned char dat)
{
unsigned int i;
for(i=0;i<8;i++)
{
if(dat&0x01)
{
//输出高电平
MOSI_OUTPUT_H();
}
else
{
//输出低电平
MOSI_OUTPUT_L();
}
dat >>= 1;
//产生上升沿
//写入
SCK_OUTPUT_L();
delay_us(10);
SCK_OUTPUT_H();
delay_us(10);
}
}
main.c
#include "spi.h"
void delay_ms(int ms)
{
int i,j;
for(i=0;i<ms;i++)
{
for(j=0;j<1000;j++);
}
}
int main()
{
SPI_init();
int i,j,k,l=0;
int num1[10] = {0xFC,0x60,0xDA,0xF2,0x66,0xB6,0xBE,0xE0,0xFE,0xF6};
int num2[4] = {0x10,0x20,0x40,0x80};
while(1)
{
for(i=0;i<10;i++) //让LED灯在相同数字持续闪10次
{
SPI_write(num2[3]); //控制位
SPI_write(num1[0]); //控制段
//NSS管脚有一个上升沿的输出,将移位寄存器的数据下沉,并行输出
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H();
delay_ms(10);
SPI_write(num2[2]); //控制位
SPI_write(num1[l]); //控制段
//NSS管脚有一个上升沿的输出,将移位寄存器的数据下沉,并行输出
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H();
delay_ms(10);
SPI_write(num2[1]); //控制位
SPI_write(num1[k]); //控制段
//NSS管脚有一个上升沿的输出,将移位寄存器的数据下沉,并行输出
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H();
delay_ms(10);
SPI_write(num2[0]); //控制位
SPI_write(num1[j]); //控制段
//NSS管脚有一个上升沿的输出,将移位寄存器的数据下沉,并行输出
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H();
delay_ms(10);
}
j++; //让第一位数字增加1
if(j==10)
{
j=0; //将第一位归零
k++; //将第二位进位1
if(k==10)
{
k=0; //将第二位归零
l++; //将第三位进位1
}
}
}
return 0;
}
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_write(unsigned char dat);
#endif