实验目标:
硬件:STM32MP157AAA开发板+拓展板
管脚:拓展板上数码管(M74HC595),由下图可知,数码管通过SPI与核心板通信,时钟(S)CK对应PE12、主机输出从机输入(MOSI)对应PE14、主机输入从机输出(MISO)对应PE13、从设备选择(CSN)对应PE11,由于当前电路SPI只有一个从设备,因此在硬件层面上将PE11常置为低电平,表示SPI主机连接此数码管。
下图为数码管(M74HC595)的pin脚连接及说明、逻辑符号:
下图为数码管(M74HC595)的SPI收发逻辑,由图可知,该数码管存在串口输入(SERIAL IN)/输出口(SERIAL OUT)、时钟(SCK)、移位寄存器输入清空(SCLR)、锁存器输入使能(RCK)、移位寄存器(SHIFT REGISTER)、锁存器(STORAGE REGISTER)。
图二可知,拓展板使用了两个数码管(M74HC595)芯片来进行数码管控制,由于STM32MP157AAA只给一个数码管(M74HC595)发送SPI数据,主机需要给该数码管发送两组数据,第一组数据经过芯片1,由芯片1再发送给芯片2,表示芯片的位(表示几个数码管,由图二可知有4个数码管),第二组数据在芯片1中处理,表示芯片的段(表示数码管有几个发光二极管组成,由图二可知由8个发光二极管)。
通过图六可知芯片各管脚在不同状态下的操作代表的意义,了解即可:
梳理:
在数码管(M74HC595)芯片中的移位寄存器(SHIFT REGISTER)处理数据是从低位开始,所以需要以低位在前高位在后的方式发送,如第一组控制位的数据,需要控制数码管第一位使能,字节应当是0B10000000,反转后实际是0B00000001=0X1。
#ifndef _M74HC595_H_
#define _M74HC595_H_
#include "stm32mp1xx_rcc.h"
#include "stm32mp1xx_gpio.h"
#include "delay.h"
#define FIRST_M74HC 0X1 //第一个灯亮
#define SECOND_M74HC 0X2 //第二个灯亮
#define THIRD_M74HC 0X4 //第三个灯亮
#define FORTH_M74HC 0X8 //第四个灯亮
#define ALL_M74HC 0XF //全部灯亮
#define MATH_0 0X3F
#define MATH_1 0X06
#define MATH_2 0X5B
#define MATH_3 0X4F
#define MATH_4 0X66
#define MATH_5 0X6D
#define MATH_6 0X7D
#define MATH_7 0X07
#define MATH_8 0X7F
#define MATH_9 0X6F
void m75hc595_init(); //初始化m75hc595
void m74hc595_write_byte(unsigned char m74hc_posi, unsigned char m74hc_date); //写入两组数据,第一个表示位,第二个表示段
void m74hc595_write_byte1(unsigned char m74hc_posi); //写入一组数据,分两次写入,第一次写入位,第二次写入段
#endif
初始化m74hc595主要配置GPIO输入输出模式和各寄存器,m74hc595_write_byte发送两组数据:
#include "m74hc595.h"
void m75hc595_init()
{
//使能GPIO外设时钟
RCC->MP_AHB4ENSETR |= (0X1<<4);
//PE11设置为输出 NSS
GPIOE->MODER &= (~(0X3<<22));
GPIOE->MODER |= (0X1<<22);
GPIOE->OTYPER &= (~(0X1<<11));
GPIOE->PUPDR &= (~(0x3<<22));
GPIOE->OSPEEDR &= (~(0x3<<22));
//PE12设置为输出 SCK
GPIOE->MODER &= (~(0X3<<24));
GPIOE->MODER |= (0X1<<24);
GPIOE->OTYPER &= (~(0X1<<12));
GPIOE->PUPDR &= (~(0x3<<24));
GPIOE->OSPEEDR &= (~(0x3<<24));
//PE13设置为输入 MISO
GPIOE->MODER &= (~(0X3<<26));
//PE14数值为输出 MOSI
GPIOE->MODER &= (~(0X3<<28));
GPIOE->MODER |= (0X1<<28);
GPIOE->OTYPER &= (~(0X1<<14));
GPIOE->PUPDR &= (~(0x3<<28));
GPIOE->OSPEEDR &= (~(0x3<<28));
//PE11输出低电平
GPIOE->ODR &= (~(0X1<<11));
//PE12输出低电平
GPIOE->ODR &= (~(0X1<<12));
}
void m74hc595_write_byte1(unsigned char date)
{
//
int i;
for(i = 0; i < 8; i++)
{
//输出高位8bit,再发送地位
if (date & 0x80) // 最高位为高
{
//PE14输出高电平
GPIOE->ODR |= (0X1<<14);
}
else
{
//PE14输出低电平
GPIOE->ODR &= (~(0X1<<14));
}
//PE12输出低电平
GPIOE->ODR &= (~(0X1<<12));
//延时等待稳定
delay(10);
//PE12输出高电平
GPIOE->ODR |= (0X1<<12);
date <<= 1;//左移1位,读下一个bit数据
}
}
void m74hc595_write_byte(unsigned char m74hc_posi, unsigned char m74hc_date)
{
//
int i;
for(i = 0; i < 8; i++)
{
//输出高位8bit,再发送地位
if (m74hc_posi & 0x80) // 最高位为高
{
//PE14输出高电平
GPIOE->ODR |= (0X1<<14);
}
else
{
//PE14输出低电平
GPIOE->ODR &= (~(0X1<<14));
}
//PE12输出低电平
GPIOE->ODR &= (~(0X1<<12));
//延时等待稳定
delay(10);
//PE12输出高电平
GPIOE->ODR |= (0X1<<12);
m74hc_posi <<= 1;//左移1位,读下一个bit数据
}
for(i = 0; i < 8; i++)
{
//输出高位8bit,再发送地位
if (m74hc_date & 0x80) // 最高位为高
{
//PE14输出高电平
GPIOE->ODR |= (0X1<<14);
}
else
{
//PE14输出低电平
GPIOE->ODR &= (~(0X1<<14));
}
//PE12输出低电平
GPIOE->ODR &= (~(0X1<<12));
//延时等待稳定
delay(10);
//PE12输出高电平
GPIOE->ODR |= (0X1<<12);
m74hc_date <<= 1;//左移1位,读下一个bit数据
}
}
简单调用配置第一个数码管显示数字5:
#include "m74hc595.h"
int main()
{
m75hc595_init();
while(1)
{
m74hc595_write_byte(FIRST_M74HC, MATH_5);
//PE11输出低电平
GPIOE->ODR &= (~(0X1<<11));
//延时
delay(10);
//PE11输出高电平
GPIOE->ODR |= (0X1<<11);
delay_ms(1000);
}
return 0;
}
标签:STM32MP157AAA,M74HC595,开发板,数码管,m74hc595,0X1ODR,MATH,define
From: https://blog.csdn.net/weixin_72755055/article/details/145041251