这一篇,我们延续解析 LED 7 节显示 的寄存器设定方法。虽然 Header 档 被 include 了好多个,却没有全部都用到;所以,我们还是从 main() 的主程式寻找那些被用到的 变数与涵式做解析。
我们从下面三个出发:
1. LED_SMG_Init(); //
2. LED_Init(); //LED
3. TIM3_Init(19,7199);//
(其中 Stm32_Clock_Init(9); 、 delay_init(72); 和 uart_init(72,115200); 这三个不在这次说明。)
先分析线路图
从 MCU 的配置了解到
- GPIOB 3/4/5 输出到 74HC595 的 SCKL/LCKL/DATA
- GPIOC 10/11/12 输出到 74HC138 的 A0/A1/A2
- 74HC138 是一颗 3 对 8 的选择器,3 个 bit 可以有 8 种状态负责控制 8 个 7 节显示管。
- 74HC595 是一颗 ”串入并出“ 8-bits 移位寄存器:
74HC595 解析
这个是 脚位的定义图,不过,名称写法不一样,我用红色字体补上了!注意 脚位 11、12、14 四个就好。
下图就是这几个脚位对输出的影响:
请观察最上面的三条时序线,这是写程式是要使用的.74HC595 的动作概念图如下:
74HC138 解析
74HC138 比较简单,前面三根线一上讯号,后面的对应输出会立即反应。
smg.h 内容
#ifndef _LED_SMG_H
#define _LED_SMG_H
#include "sys.h"
//
//
74HC138
#define LED_A0 PCout(10) //A0 == GPIOC bit 10
#define LED_A1 PCout(11) //A1 == GPIOC bit 11
#define LED_A2 PCout(12) //A2 == GPIOC bit 12
74HC595
#define LED_DS PBout(3) //
#define LED_LCLK PBout(4) //
#define LED_SCK PBout(5) //
void LED_SMG_Init(void); //设定几个寄存器的结构
void LED_Refresh(void); // 把 74HC595 后端到 7 节显示管的资料更新
void LED_Write_Data(u8 duan,u8 wei);// 把要显示的字型用串联的方式送进 74HC595
#endif
LED_Init();
这些是和前几篇一样的,所以,不再这里解析了。
void LED_Init(void)
{
RCC->APB2ENR|=1<<4;
GPIOC->CRL&=0X00000000;
GPIOC->CRL|=0X33333333;
GPIOC->ODR|=(1<<0)|(1<<1)|(1<<2)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<7);//PC.0~7
}
LED_SMG_Init();
以下的程式是 smg.c 的内容,我把说明写在注解上:
#include "smg.h"
#include "delay.h"
//
/
{
RCC->APB2ENR|=1<<3; // 选择 GPIOB
RCC->APB2ENR|=1<<4; // 选择 GPIOC
RCC->APB2ENR|=1<<0; // 选择 AFIO
JTAG_Set(SWD_ENABLE); //这个在nano 板上还没有用到
GPIOB->CRL&=0XFF000FFF;
GPIOB->CRL|=0X00333000;// 设定 GPIOB PB3~5
GPIOC->CRH&=0XFFF000FF;
GPIOC->CRH|=0X00033300;//设定 GPIOC PC10~12(高位)
GPIOB->BRR = 1<<3|1<<5; // 设定bit 3--DATA 、bit 5--SCKL 为 ”0“
GPIOB->BSRR = 1<<4; //设定 bit 4 --LCKL 为 ”1”
GPIOC->BSRR = 1<<10|1<<11|1<<12; //设定 bit 10/11/12 为 ”1”
}
//74HC138 digital selected
//num: the digital of 7_seg LED 0-7()
void LED_Wei(u8 num)
{
LED_A0=num&0x01; //把需求的 3 个 bit 的 bit-0 送到 GPIOC bit 10 (见smg.h 的定义)
LED_A1=(num&0x02)>>1; //把需求的 3 个 bit 的 bit-1 送到GPIOC bit 11 (见smg.h 的定义)
LED_A2=(num&0x04)>>2; //把需求的 3 个 bit 的 bit-2 送到 GPIOC bit 12 (见smg.h 的定义)
}
//74HC595 Serial_in_parall_out
//duan: 已经被转化成字型图案的资料,可以被成为 7-节显示管图案
//wei: 8 个 7-节显示管位置 0-7
void LED_Write_Data(u8 duan,u8 wei)
{
u8 i;
for( i=0;i<8;i++)//
{
LED_DS=(duan>>i)&0x01;
LED_SCK=0;
delay_us(5);
LED_SCK=1;
}
// LED_SCK 在 “0”、 “1”的过程 就是把 8 bit 一个一个推进74HC595,
LED_Wei(wei);// 驱动 74HC138的位置显示
}
//74HC595
void LED_Refresh(void)
{
LED_LCLK=1;
delay_us(5);
LED_LCLK=0;
}
// LED_LCLK 在 “0”、 “1”的过程 就是把 已经 一个一个推进74HC595 的 8 bit 送到后端输出。
//整个写入动作一定是,下面两个涵式连续执行
LED_Write_Data(u8 duan,u8 wei);
LED_Refresh();
有兴趣的,可以看看下面这张线路图:
TIM3_Init(19,7199);
下面这个涵式,本篇文不解析,留在后面讨论“中断”时再一起说明
void TIM3_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<1; //TIM3
TIM3->ARR=arr; //
TIM3->PSC=psc; //
TIM3->DIER|=1<<0; //
TIM3->CR1|=0x01; //
MY_NVIC_Init(0,3,TIM3_IRQn,2);//
}
下面这个涵式在 sys.c 的档案里,本篇不解析,留在“中断”时再一起说明
//在 sys.c 的档案里,
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group)
{
u32 temp;
MY_NVIC_PriorityGroupConfig(NVIC_Group);//
temp=NVIC_PreemptionPriority<<(4-NVIC_Group);
temp|=NVIC_SubPriority&(0x0f>>NVIC_Group);
temp&=0xf;//
NVIC->ISER[NVIC_Channel/32]|=(1<<NVIC_Channel%32);//
NVIC->IP[NVIC_Channel]|=temp<<4;//
}
以上,七节显示管在(正点原子 STM32F103 nano开发板)上的程式解析到此。