该项目涉及使用 ATmega328 设计七段显示 (SSD) I2C 驱动程序。
七段显示器通常采用十针封装。虽然八个引脚对应于八个 LED,但其余两个引脚(中间)是公共的并且内部短路。因此,当使用微控制器操作七段 LED 显示屏时,需要 8 个引脚来控制显示屏中的各个 LED,使用解码器可以将其减少到 4 个。随着越来越多的 SSD 添加到显示器中,这个数字会增加。
然而,在大多数应用中,使用单个数字七段显示器 (SSD) 可能不足以显示全部信息,因此多个 SSD 单元并联连接。为了显示不同的字符、符号或数字,每个 SSD 上显示的数据必须不同。但是,要同时驱动多个此类 SSD,控制它们所需的引脚数乘以正在使用的 SSD 数量。由于微控制器或驱动器上可用的 I/O 引脚数量有限,这将成为一个重大问题。该问题最广泛使用的解决方案是 SSD 数据的时分复用。在任何时刻,控制器或 SSD 解码器仅在单个 SSD 上运行,而不是同时在多个 SSD 上运行。这必须以足够快的速度完成以避开人类的视觉暂留,但必须足够慢以使显示屏上的 LED 有足够的时间来执行切换动作。使用通常由晶体管作为开关组成的另一个电路来选择单个 SSD。
除了在 SSD 显示屏上显示信息外,微控制器可能还需要执行其他功能,这可能需要也可能不需要使用 I/O 线。但是,这可能会影响 SSD 的显示时序,并可能导致不必要的暂停或关闭显示,直到 CPU 完成执行相应的指令集。
在将微控制器与 SSD 显示器连接的情况下,使用另一个微控制器作为驱动程序作为主微控制器的外围设备会非常有帮助。它还可以使显示系统隔离,并且可以使主微控制器自由执行其他指令。驾驶员必须注意显示系统中适当组件的时序和切换。主控制器和 I2C 驱动控制器之间的接口可以使用各种通信协议来完成,例如 SPI(串行外设接口)、UART(通用异步接收器发送器)、I2C(内部集成电路)等。其中,UART 是不可扩展,仅适用于固定的设备到设备通信,并且像 SPI 一样,不保证验证数据是否已正确发送。I2C 提供了所有这些优势,并且只需 2 条时钟 (SCL) 线和数据 (SDA) 线即可实现成本更低。I2C 还允许同一总线上的多个主机和从机,因此多个设备可以访问同一资源(SSD 显示器)。
用作主机的设备:Arduino UNO R3
用于驱动的微控制器:Atmel ATMEGA328(启动加载)
使用的编程器:FTDI R232RL(USB转串口TTL逻辑)
使用的编程平台:Arduino IDE 1.8.9
显示类型:6x1 SSD LED共阳极显示
SSD显示器与驱动的连接如下:
I2C 主设备(主控制器)从连接到其 ADC 引脚 A0 的 LDR 收集数据,并使用从地址将数据传输到 I2C 从设备(SSD 驱动器)。驱动程序在复位时在 SSD 显示屏上显示从地址。当它从主设备接收到数据时,它会一次更改数据缓冲区上的一个数字的数据,并继续将缓冲区上的数据显示到 SSD 显示器上。
LUT(查找表)将被写入主设备以获得更大的灵活性。段的数据被认为是二进制 1 表示 LED 亮,但是,使用的设备是共阳极类型的,因此,在显示之前,驱动程序将逻辑反转。主机首先发送数字位置的地址,然后是要由段显示的数据。该地址应在 1-6 范围内,如硬件中使用的那样。驱动程序拒绝此范围之外的任何地址。
从站:SSD_Driver.ino
#include //library;
int flag=1,m=0,n=0; //preset conditions;
byte arr[6]={0,0,0,0,0,0}; //initial buffer;
int segment[8]={0,1,2,3,4,5,6,7}; //segment/LED a,b,c,d,e,f,g,h;
int select[6]={13,12,11,10,9,8}; //digit number 1,2,3,4,5,6;
byte LUTmap=B11111111; //initial state – all LEDs off;
void setup() {
for(int i=0;i<=13;i++)
pinMode(i,OUTPUT); //all pins are output;
callforsegment(B00000000); flag++; //select digit 1;
callforsegment(B11111100); flag++; //display 0;
callforsegment(B00000010); flag++; //select digit 3;
callforsegment(B11110010); flag++; //display 3;
callforsegment(B00000011); flag++; //select digit 4;
callforsegment(B11111110); flag++; //display 8;
callforsegment(B00000100); flag++; //select digit 5;
callforsegment(B01101110); flag++; //display H(hex address);
Wire.begin(0x38); //i2c slave address for the driver;
Wire.onReceive(receiveEvent); //action on receiving data via i2c bus;
}
void segWrite(byte a) {
LUTmap=~a; //convert to common anode logic;
for(int i=0;i<8;i++)
//display to each segment in a digit;
digitalWrite(segment[i],bitRead(LUTmap,7-i));
}
void loop() {
for(int i=0;i<6;i++) {
digitalWrite(select[i],HIGH); //selecting one of the digits;
segWrite((byte)arr[i]); //writing data to the digit;
delay(5); //ON time;
digitalWrite(select[i],LOW); //deactivating the selected digit;
}
}
void callforsegment(int a) {
if(flag%2==1 && a<=7 && a>=0)
m=a; //first byte about digit location;
else {
n=a; //second byte about data for the digit;
flag=0;
}
arr[m]=(byte)n; //store data to the buffer space;
}
void receiveEvent(int howMany) {
while (1 < Wire.available()) //loop through all except last;
char c = Wire.read(); //receive byte as a character;
int x = Wire.read(); //receive byte as an integer;
callforsegment(x);
flag++;
}
主:ADC_master.ino
#include
#include //include library;
SSDmaster device(0x38); //address of slave driver;
void setup() {
Wire.begin();
}
void loop() {
int ldrval=analogRead(A0); //variable to store ADC data;
device.ssdDisplay(1,B00011100); //display L;
device.ssdDisplay(2,B01111010); //display D;
device.ssdDisplay(3,B00001010); //display R;
device.ssdDisplaynum(4,(byte)ldrval); //display ADC value;
delay(250); //rate of updation;
}
上电驱动显示 I2C 从地址。当与识别其从地址的适当 I2C 主设备连接时,从主设备发送的数据(在这种情况下为光强度)会打印到显示器上。
使用 SSD_Driver 库构建所需的系统。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !