STM32+Aip1629A点亮级联米字数码管

本文介绍了使用STM32F10x微控制器通过模拟I2C通信来配置Aip1629ALED驱动芯片,实现数码管的灰度控制和动态显示。详细阐述了数码管显示原理、I2C通信概念以及嵌入式程序的编写,包括GPIO配置、驱动接口实现和輝度控制。并提供了驱动接口的测试代码,用于数码管的上电自检。

STM32F10x是意法半导体推出的32位基于Arm® Cortex®-M处理器的主流微控制器族,本文的实现使用其作为MCU,嵌入式程序运行在这个平台之上。Aip1629A是一款LED驱动专用电路集成芯片,显示模式是16段×8位,封装形式SOP32。数码管采用共阴极2位米字型数码管5421AB。它们共同实现在常见工业产品中需要显示实时显示数字与字母的功能。

嵌入式代码使用STM32平台提供的GPIO模拟类I2C通信配置Aip1629A灰度以及位/段亮灭刷新数据。Aip1629A则根据配置以不同占空比刷新各个级联的米字型数码管位/段数据,实现数码管不同亮度的数字与字母动态显示功能。

目录

概念说明

实现原理

嵌入式程序

IO口模拟类I2C通信

驱动接口实现

接口测试


概念说明

我们先来解释一下后续文章中使用的一些概念:

  • I2C:本名IIC(Inter-Integrated Circuit)总线,主要用于在板上连接微控制器与外围芯片。总线由两根线构成:时钟线(CLK)与数据线(DIO),可以看出是同步半双工通信通信总线。
  • 数码管:LED数码管(LED Segment Displays)由多个发光二极管封装在一起组成“8”或“米”字型的器件,引线已在内部连接完成,只需引出它们的各个笔划,公共电极。
  • 数码管位/段:数码管的段(SEGMENT)指的是构成一个数码管的每个发光二极管,而位(GRID)指的是这个这个数码管的“片选”引脚。
  • 共阴/共阳:共阳极是将所有段对应的发光二极管阳极接倒一起,共阴极是将所有段对应的发光二极管阴极接到一起,下图是一个7段共阴数码管:
  • 辉度:Aip1629A芯片通过实现不同占空比来动态刷新数码管实现不同灰度(亮度)的数字/字母显示。

实现原理

数码管显示的实现原理比较简单也比较典型。LED驱动专用芯片Aip1629A根据锁存器等数据状态,负责驱动显示器件(15段数码管)正确显示数字或字母,MCU则根据Aip1629A手册提供的通信传输格式以及寄存器说明来正确配置Aip1629A从而控制数码管随时显示所需显示的数字与字母。下图为实现原理的示意图:

嵌入式程序

下面是嵌入式程序的编写,主要包括通信链路的打通(寄存器能够正常配置与读取),驱动接口的封装(包括初始化,点亮一个LED数码管显示字符,熄灭一个数码管等),以及一个小的测试函数用于上电自检。

IO口模拟类I2C通信

Aip1629A芯片通信使用的是类I2C物理链路层总线协议,下面是它的指令数据传输过程,可以看出可以抽象成通过传送8位以及16位数(指令或者数据)两个接口实现:

 模拟这种通信,首先我们根据电路图的连接,正确配置这三个IO口并提供DIO(代码中以SDA命名数据线)不同方向(输入输出)的接口:

#define AIP1629_RCC 			RCC_APB2Periph_GPIOB			//RCC
#define AIP1629_PORT 		    GPIOB							//PORT
#define AIP1629_SDA 			GPIO_Pin_15						//SDA
#define AIP1629_SCL 			GPIO_Pin_13						//SCL
#define AIP1629_STB 			GPIO_Pin_12						//STB


void Aip1629_GPIO_INIT()//IO口初始化		
{
	GPIO_InitTypeDef GPIO_INIT;
	RCC_APB2PeriphClockCmd(AIP1629_RCC ,ENABLE);
	
	GPIO_INIT.GPIO_Mode=GPIO_Mode_Out_PP;
	
	GPIO_INIT.GPIO_Pin=AIP1629|AIP1629|AIP1629;
	GPIO_INIT.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(AIP1629_PORT,&GPIO_INIT);
}
void Aip1629_SDA_IN(void)//设置SDA为输入		
{
	GPIO_InitTypeDef GPIO_INIT;		
	GPIO_INIT.GPIO_Mode=GPIO_Mode_IN_FLOATING;//GPIO_Mode_IPU
	GPIO_INIT.GPIO_Pin=AIP1629_SDA;
	GPIO_INIT.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(AIP1629_PORT,&GPIO_INIT);
}
void Aip1629_SDA_OUT(void)//设置SDA为输出			
{
	GPIO_InitTypeDef GPIO_INIT;
	GPIO_INIT.GPIO_Mode=GPIO_Mode_Out_OD;//GPIO_Mode_Out_PP
	GPIO_INIT.GPIO_Pin=AIP1629_SDA;
	GPIO_INIT.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(AIP1629_PORT,&GPIO_INIT);
}

下面是实现这种类I2C协议写入8/16位数(数据或者命令):

#define AIP1629_SDA_H GPIO_SetBits(AIP1629_PORT,AIP1629_SDA)
#define AIP1629_SDA_L GPIO_ResetBits(AIP1629_PORT,AIP1629_SDA)
#define AIP1629_SCL_H GPIO_SetBits(AIP1629_PORT,AIP1629_SCL)
#define AIP1629_SCL_L GPIO_ResetBits(AIP1629_PORT,AIP1629_SCL)
#define AIP1629_STB_H GPIO_SetBits(AIP1629_PORT,AIP1629_STB)
#define AIP1629_STB_L GPIO_ResetBits(AIP1629_PORT,AIP1629_STB)
void Aip1629delayus(unsigned  int k)//延时1us
{
	
	unsigned char i=8;
	unsigned int j=0;
	
	
	for(j=0;j<k;j++)
	{
		while(i)
		{
			i--;
		}
	}
}
void _Aip1629_Write8(uchar wr_data)//发送8位数
{
   uchar i;
   Aip1629delayus(1);
   AIP1629_STB_L;//stb =0;	   

	
   Aip1629delayus(1);
   
   for(i=0;i<8;i++)
	 {
	     AIP1629_SCL_L;//clk =0;
	     Aip1629delayus(1);
	     if(wr_data & 0x01) 
		 {
		     AIP1629_SDA_H;
	     }
		 else 
		 {
		     AIP1629_SDA_L;
		 }
	     Aip1629delayus(1);
	     wr_data >>= 1;
	     AIP1629_SCL_H;//clk =1;
		 Aip1629delayus(1);
	   }
}

void _Aip1629_Write16(uint wr_data)//发送16位数
{
	uchar temp;
	temp=wr_data&0xff;
	_Aip1629_Write8(temp);
	temp=(wr_data>>8)&0xff;
	_Aip1629_Write8(temp);
		
}

虽然没有见到我们熟悉的IIC_Start()和IIC_Start()接口,我们至此实现了这种类I2C的通信。

驱动接口实现

数码管为业务层提供的驱动接口包括:

  • Aip1629A_INIT:驱动芯片初始化。
  • Aip1629A_CloseOneGrid:关闭某位LED数码管。
  • Aip1629A_DisplayNumber:点亮某位LED数码管显示数字/字符。
  • Aip1629A_ChangeBrig:更改显示辉度。

驱动管理结构体实现简单,未考虑多个Aip1629A芯片情况,仅保存了辉度数值。

这里边还有一个数组需要我们实现数字/字符到数码管段显示的映射表(字模),比如字符零,需要哪些段亮起那些段熄灭,根据硬件接线以及数码管实现转化成一个16位数(每位对应数码管段的亮灭状态)。

下面是驱动接口实现代码:

typedef struct
{
	Bright brig;
}DeviceAip1629;

DeviceAip1629 StrAip1629;//驱动管理结构体

//数字与字符到数码管段显示映射表。
uint CODE[Display16Number+1+26] = {0x003f,0x0006,0x00db,0x00cf,0x00e6,0x00ed,0x00fd,0x0007,0x00ff,0x00ef,0x0c86,0x00fc,0x0039,0x00de,0x00f9,\
								0x00f1,0x0018f,0x00f6,0x1209,0x001e,0x2470,0x0038,0x1536,0x2136,0x00dc,0x00f3,0x0187,0x20f3,0x018d,0x1201,\
								0x003e,0x2106,0x2A36,0x2d00,0x1500,0x0c09,0x00,0xc0,0x0c86,0x0fc,0xD8,0xde,0xFB,0x71,0x18f,0xf4,0x1200,0x1e,0x2470,0x38,\
								0x10d4,0xd4,0xdc,0xf3,0x187,0x20f3,0x18d,0x10c0,0x1c,0x2106,0x2814,0x2d00,0xee,0x0c09};


void Aip1629_CloseOneGrid(uchar grid)//熄灭数码管
{
	grid=grid&0x0f;
	_Aip1629_Write8(0x40);
	AIP1629_STB_H;
	_Aip1629_Write8(0xc0+grid*2);
	_Aip1629_Write16(0x00);
	Aip1629_STB_H;
}

void Aip1629_INIT(Bright brig)	//Aip1629驱动初始化
{
	unsigned int i=0;

	Aip1629_GPIO_INIT();
	for(i=0;i<6;i++)
	{
		Aip1629_CloseOneGrid(i);
	}
	
	StrAip1629.brig=brig;
	
	_Aip1629_Write8(Tm16929.brig);
	AIP1629_STB_H;
}
void Aip1629_ChangeBrig(Bright brig)//修改辉度
{
	StrAip1629.brig=brig;	
	_Aip1629_Write8(StrAip1629.brig);
	AIP1629_STB_H;
}

void Aip1629_DisplayNumber(uchar grid,uint number,uchar point)//显示字符
{
	static int SetBrig=0;
	
	SetBrig++;
	if(SetBrig%6==0)
	{
		_Aip1629_Write8(StrAip1629.brig);
		AIP1629_STB_H;
	}
	
	//unsigned int temp=0;
	AIP1629_STB_H;//stb = 1;
	AIP1629_SCL_H;//clk = 1;
	AIP1629_SDA_H;//dio = 1;
	
	grid=grid&0x0f;
	_Aip1629_Write8(0x40);
	AIP1629_STB_H;
	_Aip1629_Write8(0xc0+grid*2);
	if(point==0)
	{
		_Aip1629_Write16(CODE[number]);
	}
	else
	{
		_Aip1629_Write16(CODE[number]+0x4000);
	}
	AIP1629_STB_H;
}

接口测试

测试接口实现使用所有数码管将所有字符打印一遍,这个功能可以用于上电自检或者产品老化。代码如下:

typedef enum __Bright__
{
      AIP1629Lv1=0x88, AIP1629Lv2, AIP1629Lv3, AIP1629Lv4, AIP1629Lv5, AIP1629Lv6, AIP1629Lv7,AIP1629Lv8
}Bright;


void LEDTest_Delay(uint32 u32count)
{
	uint32 i = 0;
	for(i=0;i<u32count*100;i++)
	{
		;;
	}
}

void Aip1629_Test(void)
{
	uchar i;
	uchar k;
	
	Aip1629_INIT(AIP1629Lv8);
	
	for(i=0;i<sizeof(CODE);i++)
    {
		for(k=0;k<6;k++)
		{
			Aip1629_DisplayNumber(k,i,1);//将小数点段点亮
			LEDTest_Delay(50000)
		}
	}
}

下图是米字型数码管所有位/段点亮的效果:


十六宿舍 原创作品,转载必须标注原文链接。

©2023 Yang Li. All rights reserved.

欢迎关注 『十六宿舍』,大家喜欢的话,给个👍,更多关于嵌入式相关技术的内容持续更新中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值