由于时间没有用时间计时器操作,有些误差,后续有空会翻新计时器版本
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()
{
int i,j,k,l,m;
SPI_init();
//先发送位
//在发送段
while(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);
}*/
for(i=5;i>=0;i--){
for(j=9;j>=0;j--){
for(k=5;k>=0;k--){
for(l=9;l>=0;l--){
for(m=200;m>=0;m--){
//显示分钟十位
SPI_write(0x80);
SPI_write(num[i]);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H();
//delay_ms(1000);
//显示分钟个位
SPI_write(0x40);
SPI_write(num[j]);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H();
// delay_ms(1000);
//显示秒钟十位
SPI_write(0x20);
SPI_write(num[k]);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H();
// delay_ms(1000);
//显示秒钟个位
SPI_write(0x10);
SPI_write(num[l]);
NSS_OUTPUT_L();
delay_ms(1);
NSS_OUTPUT_H();
//delay_ms(1000);
}
}
}
}
}
}
return 0;
}
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)
{
unsigned char i;
for(i=0;i<8;i++){
//先发送低位再发送高位
// 判断条件写1写0
if(dat & 0x1){
MOSI_OUTPUT_H();
}else{
MOSI_OUTPUT_L();
}
dat >>=1;
// 上升沿
SCK_OUTPUT_L();
delay_us1(10);
SCK_OUTPUT_H();
delay_us1(10);
}
}
spi.h文章来源:https://www.toymoban.com/news/detail-549678.html
#ifndef __SPI_H__
#define __SPI_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
// MOSI对应的引脚输出高低电平的信号
#define MOSI_OUTPUT_H() do{GPIOE->ODR |= (0x1 << 14);}while(0)
#define MOSI_OUTPUT_L() do{GPIOE->ODR &= (~(0x1 << 14));}while(0)
// 对应595芯片的锁存引脚输出高低电平
#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)
/*
* 函数功能: SPI初始化函数,推挽输出,高速,禁止上拉和下拉
* 函数参数:无
* 函数返回值:无
*/
void SPI_init(void);
/*
* 函数功能:SPI发送数据的函数
* 函数参数:dat : 要发送的数据
* 函数返回值:无
*
*/
void SPI_write(unsigned char dat);
#endif // __SPI_H__
文章来源地址https://www.toymoban.com/news/detail-549678.html
到了这里,关于arm学习stm32之spi总线数码管倒计时的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!