基于单片机的6路抢答器设计
摘要
近年来,计算机技术析迅猛发展,使得计算机在工业,农业,国防科研及日常生活的各个领域显示了日益旺盛的生命力,它已成为各国工业发展水平的主要标志之一是发展新技术,改造老技术的强有力的武器。
目前,单片机正朝着高性能和多品种方向发展,单片机的发展正朝着CMOS 化,低功耗,小体积,大容量,高性能,低价格和外围电路的内装化等几个方面发展。近几年,由于某种原因CHMOS 技术的进步大大地促进了单片机的CMOS 化,此种芯片除了低功耗外,还具有功耗的可控性,使单片机可以工作在功耗精细管理状态,特别是IIC ,API 等串行总线的引入,可以使单片机的引脚设计得更少,单片机系统结构更加简化及规范化而我们设计出的4路抢答器是一种基于MCS-51智能锁的硬件和软件设计及实现方法,这种电路设计具有按键有效提输入错误提示控制开锁电平控制报警电路在线修改功能等多种功能保密性强灵活性高特别适用于家庭办公室学生宿舍及宾馆等场所。它具有全集成化,智能化,高精度,高性能,高可靠性和低价格等优点,是一个值得推广的一种方法。接下来我们就对方案与设计原理方框图进行比较分析。
关键字:抢答器;单片机;数码管
目 录
第一章 设计意义 ......................................................................... 1 第二章 系统总体设计 ..................................................................... 2
2.2 设计要点 ....................................................................... 2 第三章 智能抢答器系统的硬件电路 ......................................................... 3
3.1 抢答器系统电源的设计与分析 ...................................................... 3 3.2 中央控制器 ...................................................................... 3 3.3 抢答器的外围控制与分析 .......................................................... 3 3.4 抢答器的输入模块 ................................................................ 5 3.5 抢答器其他模块 .................................................................. 5 第四章 程序设计说明 .................................................................... 6
4.1 抢答主体程序 ................................................................... 6
4.1.1 程序流程 . ................................................................ 6 4.1.2 程序注释 . ................................................................ 7 4.2 数码管显示程序 ................................................................ 19
4.2.1 程序流程图 . ............................................................. 19 4.2.2 程序注释 . ............................................................... 20 4.3 蜂鸣器发声程序 ................................................................. 20
4.3.1程序流程图 ............................................................... 20 4.3.2程序注释 ................................................................. 21
第五章 设计调试及性能测定 .............................................................. 22 第六章 结论 . ........................................................................... 23 结束语 .................................................................................. 24 谢 辞 ................................................................................... 24 参 考 文 献 ............................................................................. 25 附录 元器件清单 ........................................................................ 25
1 设计意义
电子技术在不断地发展,基于单片机的控制系统已广泛应用于工业、农业、电力、电子、智能楼宇等行业,微型计算机作为嵌入式控制系统的主体与核心,代替了传统的控制系统的常规电子线路。电子技术和微型计算机的迅速发展,促进微型计算机测量和控制技术的迅速发展和广泛应用,单片机的应用已经渗透到国民经济的各个部门和领域,它起到了越来越重要的作用。本文就是单片机的其中一个具体应用,将其与抢答器的设计有机地结合起来。
在抢答过程中,为了知道哪一组或哪一位选手先答题,必须要设计一个系统来完成这个任务。因为在抢答的过程中,靠视觉是很难判断出哪组先答题。利用单片机系统来设计抢答器,就可以很好地解决上述的问题,因为单片机的动作是极其迅速的,即使两组的抢答相差的时间是微秒级的,也可轻松分辨出是哪组优先答题,本文的抢答组数可以在六组以内任意使用,当然通过扩展抢答的组数是可以大于6组的。此外还对抢答器的功能进行了一些扩展,如用不同的音乐提示回答是正确还是错误;也新增了计分功能,当抢答结束,可以知道各个组别的积分的多少。
而对我们大学生来讲,通过本次毕业设计可以巩固和加深对电子电路基本知识的理解,提高综合运用专业所学知识的能力。与此同时也培养了根据设计需要选学参考书籍,查阅相关手册、图表和文献资料的自学能力。通过设计方案的分析、论证和比较,设计计算和选取元器件、电路焊接、系统的功能调试和检测等环节,掌握了一个设计由概念到成品设计过程的各个环节,也通过电路的调试和性能指标的测试,提高实际动手能力和综合的电子设计能力。
2 系统总体设计
2.1 抢答器的设计要求
(1)系统设置复位按钮,按动后,重新开始抢答。
(2)抢答器开始时数码管显示序号0,选手抢答实行优先锁存,优先抢答选手的编号一直保持到主持人将系统清除为止。抢答后显示优先抢答者序号,并且不出现其他抢答者的序号。
(3)抢答器具有定时抢答功能。
(4)主持人按下复位开关,使得抢答器再次进入禁止状态,选手编号的LED 数字显示器灯熄灭,电路进入原来的初始状态,准备进入下一轮的抢答。
(5)扩展功能为音乐提醒和积分功能。
2.2 设计要点
根据控制系统的工作原理和执行装置,可以将系统设计分为硬件和软件两大部分。硬件设计部分,包括编写电路原理图、合理选择元器件、焊接各个元器件,然后对硬件性能进行调试、测试,以达到设计要求。软件设计部分,首先在设计之前完成系统总框图和确定各个功能模块,然后进行具体设计,包括各模块的流程图,选择合适的编程语言和软件应用程序,进行编程设计等;最后是通过软件对程序进行调试、测试,以及仿真,以达到性能的最优化。
下面是软硬件设计方法确定的。软件设计的方法与开发环境的选取有着直接的关系,本系统由于是采用51系列单片机,因此使用Keil C语言进行开发。此编程工具相比汇编语言具有结构化、适用范围大、可移植性好等特点。本系统软件设计采用模块化系统设计方法,先编写各个功能模块子程序,然后进行组合与调整,经过调试后,可以进行仿真测试,已达到设计功能要求。为配合软件的灵活设计,硬件电路是采用结构化系统设计方法,该方法保证设计电路的标准化、模块化。硬件电路的设计最重要的选择用于控制的单片机,再确定与之配套的外围芯片,使所设计的系统既经济又高性能。硬件电路设计可以在焊接元器件之前画出详细电路图,标出芯片的型号、器件参数值,根据电路图在仿真软件上进行调试,发现设计错误时立即修改,高效,准确地完成硬件设计。
3 智能抢答器系统的硬件电路
3.1 抢答器的电源控制与分析
抢答器同时供6名选手或6个代表队比赛,分别用6个按钮表示。设置一个系统清除和抢答控制按扭,以及两个抢答时间的加和减,答题时间的加和减。控制模块使用单片机,型号为STC89C51,由单片机执行程序控制各个组件实现功能。显示方面使用4位共阴极的数码管,用动态扫描的显示方式显示数字号码,并且有一个蜂鸣器发声。
3.2 中央控制器
抢答器必须用到一些显示模块,对于一般的电子设计主要考虑以下两种显示方案。 方案一:使用液晶屏显示。液晶显示屏具有轻薄短小、低耗电量、无辐射危险,平面直角显示以及影像稳定不闪烁等优势,可视面积大,画面效果好,分辨率高,抗干扰能力强的特点。但由于选手和编号信息量比较少,且由于液晶是以点阵的模式显示各种符号,编程工作量大,控制器的资源占用较多,其成本也偏高。在使用时,不能有静电干扰,否则易烧坏液晶显示芯片,不易维护。
方案二:在使用传统的数码管显示。数码管具有:低能耗、低损耗、低压、寿命长、耐老化、防晒、防潮、防火、防高(低)温,对外界环境要求低,易于维护,同时其精度高,称量快,精确可靠,操作简单。数码显示是采用BCD 编码显示数字,程序编译容易,资源占用较少。
综上所述,选用方案二,这里使用四位共阴极数码管作为显示模块。
图3-1 四位共阴极数码管
3.3 抢答器的控制模块
采用STC89C51作为系统控制器的CPU 方案。单片机算术运算功能强,软件编程灵活、自由度大,可以用软件编程实现各种算法和逻辑控制,并且由于其功耗低、体积小、技术成熟和成本低等优点,使其在各个领域应用广泛。
STC89C51单片机是一种低功耗、高性能CMOS 8位微控制器,具有8k 在系统可编程Flash 存储器, 与工业80C52产品指令和引脚完全兼容。片上Flash 允许程序存储器在系统可编程,亦适于常规编程器。在单芯片上,拥有灵巧的8位CPU 和在系统可编程Flash ,
使得STC89C51单片机为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
图3-2 STC89C51引脚图
STC89C51具有以下标准功能:8k 字节Flash ,256
字节RAM ,32位I/O口线,看门狗定时器,2个数据指针,三个16位定时器/计数器,一个6向量2级中断结构,全双工串行口,片内晶振及时钟电路。另外,STC89C51可降至0Hz 静态逻辑操作,支持2种软件可选择节电模式。空闲模式下,CPU 停止工作,允许RAM 、定时器/计数器、串口、中断继续工作。掉电保护方式下,RAM 内容被保存,振荡器被冻结,单片机一切工作停止,直到下一个中断或硬件复位为止。
89C51基本外围电路: ①时钟电路:
单片机的时钟信号用来提供单片机片内各种微操作的时间基准,时钟信号通常用两种电路形式得到:内部振荡和外部振荡。STC89C51单片机内部有一个用于构成振荡器的高增益反向放大器,引脚XTALl 和XTAL2分别是此放大电器的输入端和输出端,由于采用内部方式时,电路简单,所得的时钟信号比较稳定,实际使用中常采用这种方式,其外接晶体振荡器(简称晶振) 或陶瓷谐振器就构成了内部振荡方式,片内高增益反向放大器与作为反馈元件的片外石英晶体或陶瓷谐振器一起可构成一个自激振荡器并产生振荡时钟脉冲。外接晶体以及电容C1和C2构成并联谐振电路,它们起稳定振荡频率、快速起振的作用,其值均为30pF 左右,晶振频率选12MHz 。
图3-3 晶振电路
②复位电路:
为了初始化单片机内部的某些特殊功能寄存器,必须采用复位的方式,复位后可使CPU 及系统各部件处于确定的初始状态,并从初始状态开始正常工作。单片机的复位是靠外电路来实现的,在正常运行情况下,只要RST 引脚上出现两个机器周期时间以上的高电平,即可引起系统复位,但如果RST 引脚上持续为高电平,单片机就处于循环复位状态。复位后系统将I/O口寄存器置为0FFH ,堆栈指针SP 置为07H ,SBUF 内置为不定值,其余的寄存器全部清0,内部RAM 的状态不受复位的影响,在系统上电时RAM 的内容是不定的。复位操作有两种情况,即上电复位和手动(开关) 复位。本系统采用手动复位和上电复位组合方式。
图3-4 复位电路
3.4 抢答器的输入模块
键盘是单片机不可缺少的输入设备,是实现人机对话的纽带。
行列式键盘是用N 条I/O线作为行线,M 条I/O线作为列线组成的键盘,在行线和列线的每个交叉点上,设置一个按键中按键的个数是M*N个。这种形式的键盘结构,能够有效的提高单片机系统中I/O的利用率。
CPU 对键盘的扫描可以采用取程序控制的随机方式,即只有在CPU 空闲时才去扫描键盘,响应操作人员的键盘输入,但CPU 在执行应用程序的过程中,不能响应键盘输入,对键盘的扫描可以采用定时方式,即利用单片机内部定时器每隔一定时间对键盘扫描一次,这样控制方式,不管键盘上有无键闭合,CPU 总是定时的关心键盘状态。
最简单的编码方式就是根据I/O输入口所直接反映的相应按键,按下的状态进行编码,称按键直接状态码,对于这样编码的独立式键盘,CPU 可以通过直接读取I/O口的状态来获取按键的直接状态编码值,根据这个值直接进行按键识别,这样形式的键盘结构简单,按键识别容易。
3.5 抢答器其他模块
发声模块:经过一个三极管和电容组成的电流放大电路驱动蜂鸣器,改变通电频率从而改变发声的音调。
3. 6 系统主体原理图
控制芯片采用单片机STC89C51,显示功能采用4位的共阴极数码管,输入硬件是用独立式键盘,用蜂鸣器发声来提示抢答的成功。
图3-6 主体原理图
4 程序设计说明
4.1 抢答主体程序
4.1.1 程序流程
程序不断地扫描单片机的各个输入端口,即各个选手的按键。当有按键按下时将成功抢答的选手组号显示在数码管上,同时蜂鸣器响起,直到启动键再次被按下时则继续扫描各个输入端口,进入下一轮的抢答。
图4-1 程序流程图
4.1.2 程序注释
主题程序如下:
#include
#define uchar unsigned char #define uint unsigned int
sbit start=P3^0; //主持人按键开始 sbit reset=P3^1;
//复位
//sbit m1=P3^1; //主持人按键答对加分,按一下加一分
//sbit m2=P3^2; //答错减分
sbit add1=P3^2; //抢答时间调整,加1
sbit dec1=P3^3; //抢答时间调整,减1
sbit add2=P3^4; //答题时间调整,加1
sbit dec2=P3^5;
sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
sbit k4=P1^3;
sbit k5=P1^4;
sbit k6=P1^5; //选手按键
sbit beep=P3^6; //蜂鸣器
bit qd;
bit dt; //抢答标志位,=1时开启抢答 //答题标志位,=1时开启答题
//答题时间调整,减1 bit disp_qd_dt;
//uchar code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77}; //0-9代码
unsigned char code tab[]={0x5F,0x44,0x9D,0xD5,0xC6,0xD3,0xDB,0x45,0xDF,0xD7,0xCE,0xC7,0xDC}; //数字0-9的编码
uchar shiwei,gewei,xuanshou,count,p,second;
uchar qd_time=30,dt_time=60;
认60S
uint t,m,n,a,a1,a2,a3,a4,a5,a6;
void Timer()
{
TMOD=0x01; TH0=0x3C; //初值15536,计数50000次,每次1uS ,总计50ms
//抢答时间,默认30S ,答题时间,默
IE=0x82; //这里是中断优先级控制EA=1(开总中断),ET0=1(定时器0允许中断) ,这里用定时器0来定时
}
void tim(void) interrupt 1 using 1 //为定时中断TR0
{
}
void delay(uint z) //延时函数
{
}
void display (void) //显示函数
{
TR0=0; TH0=0x3C; //重新赋值 TL0=0xB0; TR0=1; count++; if((second=1) second--; //秒减1 else TR0=0; if((second0;x--) for(y=110;y>0;y--); //约1ms
}
shiwei=tab[second/10]; gewei=tab[second%10]; xuanshou=tab[p]; P0=gewei; P2=0x7F; delay(5); P2=0xFF; //个位位选 P0=shiwei; P2=0xBF; delay(5); P2=0xFF; //显示十位 //打开显示时间十位的位选 P0=0x80; //显示横线 P2=0xDF; delay(5); P2=0xFF; P0=xuanshou; P2=0xEF; delay(5); P2=0xFF; //选手位选
void keyscan(void)
{
if(add1==0) { display(); if(add1==0) { p=11; disp_qd_dt=0;
qd_time++;
if(qd_time>=99)
qd_time=99;
}
second=qd_time;
do
display();
while(add1==0);
}
if(dec1==0)
{
display();
if(dec1==0)
{
p=11;
disp_qd_dt=0;
qd_time--;
if(qd_time
qd_time=1;
}
second=qd_time;
do
display();
while(dec1==0);
}
if(add2==0)
{
display();
if(add2==0)
{
p=12;
disp_qd_dt=1;
dt_time++;
if(dt_time>=99)
dt_time=99;
}
second=dt_time;
do
display();
while(add2==0);
}
if(dec2==0)
{
display();
if(dec2==0)
{
p=12;
disp_qd_dt=1;
dt_time--;
if(dt_time
dt_time=1;
}
second=dt_time;
do
display();
while(dec2==0);
}
}
void init()
{
P2=0x04;
P0=0x3f;
t=0;
beep=1;
p=10;
second=qd_time;
} //初始化函数 //选手号初始为显示H ,表示等待
void main()
{
uchar i;
init();
Timer();
while(1)
{
if((qd==0)&&(dt==0))
keyscan();
display();
if(start==0)
{
if((qd==0)&&(dt==0))
{
p=10;
disp_qd_dt=0;
second=qd_time;
qd=1;
}
beep=0;
for(i=0;i
{
display();
}
beep=1;
TR0=~TR0;
do
display();
while(!start);
}
if(reset==0) //定时器设置 //在非抢答,非答题状态下 //主持人按下开始键 //蜂鸣器长响一声 //等待释放按键
{
display();
if(reset==0)
{
disp_qd_dt=0;
second=qd_time;
t=0;
p=10;
TR0=0;
beep=1;
qd=0;
dt=0;
}
do
display();
while(!reset);
}
if(qd==1)
{
{
if(k1==0)
{
display();
if(k1==0);
do display();
while(!k1);
t=1;
qd=0;
dt=1;
}
else if(k2==0)
{
display();
if(k2==0);
do
display();
while(!k2);
t=2;
qd=0;
dt=1;
}
else if(k3==0)
{
display();
if(k3==0);
do display();
while(!k2);
t=3;
qd=0;
dt=1;
}
else if(k4==0)
{
display();
if(k4==0);
do display();
while(!k2);
t=4;
qd=0;
dt=1;
}
else if(k5==0)
{
display();
if(k5==0);
do display();
while(!k2);
t=5;
qd=0;
} } else if(k6==0) { } display(); if(k6==0); do display(); while(!k2); t=6; qd=0; dt=1; if(t) { switch(t) { case 1: { } TR0=0; p=1; second=dt_time; beep=0; for(i=0;i
} for(i=0;i
{ }
TR0=0; p=5;
second=dt_time; beep=0;
for(i=0;i
display();
case 6:
{ }
TR0=0; p=6;
second=dt_time; beep=0;
for(i=0;i
display();
}
}
if(dt==1) {
//答题标志开启时
if(start==0) {
display(); if(start==0)
}
}
}
}
{ }
beep=0;
for(i=0;i
display();
}
if(second==0) { }
beep=0; qd=0; dt=0;
//为0时报警
4.2 数码管显示程序
4.2.1 程序流程图
在写程序之前需要先测出数码管显示数字时它各个引脚的电平情况,从而得出各个数字的代码,控制单片机输出不同的代码,就能显示不同的数字。本次的程序采取动态扫描的编程方式,一般显示的频率在50hz 左右,眼睛不会感到有闪烁感,因此应该适当地选择显示延时的时间。
图4-2 数码管显示程序流程图
4.2.2 程序注释
数码管显示程序如下:
void display(uchar shiwei,uchar gewei,uchar xuanshou) {P2=0xfd;
/*位选*/
P0=shiwei; /*段选*/ delay_us(80); /*延时显示*/ P2=0xfe; P0=gewei; delay_us(80); P2=0xf7; P0=xuanshou; delay_us(80); }
4.3 蜂鸣器发声程序
4.3.1程序流程图
发声部分主要是通过改变蜂鸣器的通断频率去改变声调,具体是改变高低电平的延迟时间,频率越高则声调越高,频率越低则声调越低。
图4-3 蜂鸣器发声程序流程
4.3.2程序注释
蜂鸣器发声程序如下:
void sound_ok() /* { uchar a,b; TR1=0;
for(a=4;a>0;a--) {for(b=900;b;b--)
{ beep=1; /* delay_us((a+5)*10); /* beep=0; /* delay_us((a+5)*10); /* } } }
void sound_err(void) /* {uchar a,b; TR1=0;
for(a=1;a
{ beep=1; /* delay_us((a+5)*10); /* beep=0; /* delay_us((a+5)*10); /* } } }
回答正确子程序*/ 开蜂鸣器*/
改变高电平持续时间*/ 关蜂鸣器*/
改变低电平持续时间*/ 回答错误子程序*/ 开蜂鸣器*/
改变高电平持续时间*/ 关蜂鸣器*/
改变低电平持续时间*/
5 设计调试及性能测定
数码管的调试,因为在硬件各模块中出错机会比较大的就是数码管的显示混乱。按照设计前测出的位码和段码编写一小程序,四位同时依次显示0至9,测试段码的编码是否正确,看是否有显示错误的段位。因此,本设计采用动态扫描的显示方式,然后是位码的测试,将程序改为让数码管的1至4位依次显示数字1~4,经测试后,显示正常。数码管经测试功能正常。
根据功能要求编写程序,在单独测试中各个模块的程序功能正常,但将各个部分结合在一起的时候遇到了一个问题,就是显示程序与发声程序之间有一定的冲突,例如要求在倒计时开始和结束的时候要求有一声0.5秒左右的鸣叫声,但是发现在发声的这段时间里数码管没有了显示,因为单片机在同一个时间里只能执行一条程序。经过一番努力终于想到的解决的方法,因为原来的数码管显示间隔与计时倒数是公用同一个定时器的,因此间隔过大,解决方案为:数码管显示程序用另外一个定时器来调用,并使用较小的显示间隔,这样当要发声时数码管上仍然有显示,因为这时程序在发声和显示模块之间快速的来回跳动,而且数码管没有闪烁感。
设计各个部分功能调试完毕,显示正常,发声正常,抢答正常,并且性能良好。
图5-1 调试过程图
6 结论
本设计是基于单片机的六路抢答器。系统设置复位按钮,按动后,抢答器进入禁止状态。按下启动按钮,抢答开始,选手抢答实行优先锁存,优先抢答选手的编号保持显示。抢答器具有定时抢答功能,倒数时间为30s 。主持人再次按下启动按钮,选手编号的数码管显示器熄灭,进入下一轮的抢答倒数。
结束语
这一次课程设计,它加深与巩固了我们所学的专业基础课程,例如数电和模电并将其综合运用,提高了我们综合运用知识的能力还有就是将理论运用于实践,另一方面,培养了我们对专业知识学习的趣;同时也提高了我们分析问题的能力。
这次课程设计的设计流程我采用分块的设计顺序,优化了设计流程使之更符合逻辑但是需要注意的是,在其中每个环节必须认真进行,如果某模块电路没有设计好,或者存在错误,
则总的电路必然会受到影响,所以在设计时应该考虑到实际情况,尤其是对芯片的择上。有时候会因为一个极小的疏忽而导致整个电路无法运行,例如,在仿真过程,所选的数字显示器自带了译码功能,如果再接译码器,将无法显示数。在连线时,更应该仔细,一不小心就会短路。
通过这次课程设计,我基本掌握了用Protues 软件仿真电路图并进行仿真分析,且初步掌握了电子电路的设计方法,在以后的学习中还需多加练习,熟练掌握,为以后的工作做准备。
谢 辞
在整个毕业设计中,我得到了指导老师的热心指导和帮助,感谢您,您辛苦了! 时光的流逝也许是客观的,然而流逝的快慢却纯是一种主观的感受。忽然间意识到,原来三年已经过去,到了该告别的时候了。一念至此,不禁有些惆怅。想到自己要踏上人生的另外一个征途,激动之余也有点不舍。
回想大学三年,首先要感谢的就是所有教导过我的老师,他们都有在不同的领域给了我启发,提升了我的专业知识与技能,也使我学到了很多为人处事的道理,这就是一种成长的过程。然后要感谢的是我大学所有的朋友,有了你们互相扶持,互相鼓励,我的大学生活才会添上各种不同的色彩,虽然我们都没有明说,我知道我们都很珍惜彼此。还有就是我的父母,你们的养育与培养之恩我毕生不忘,我会努力变强,承担照顾你们的责任。
参 考 文 献
[1]谢振辉. 改进式MCS-51单片机实验. 北京:科学出版社,2006: 121-156.
[2]李朝青. 单片机原理及接口技术. 北京:北京航空航天大学出版社,2006: 112-132. [3]康华光, 邹寿彬. 电子技术基础数字部分. 第五版. 北京:高等教育出版社,2005: 72-96.
[4]胡伟,季晓衡. 单片机C 程序设计及应用实例. 北京:人民邮电出版社,2003: 84-112. [5]曹建树,夏云生,曾林春. 51单片机实用教程. 北京:中国石化出版社,2008: 66-87.
附录 元器件清单
元器件清单 STC89C51 4位公阴数码管 晶振(12M) 三极管极管
数量 1 1 1 1
按键 蜂鸣器(5V )
排阻 电阻(10k )
电源 电容(30pf )
开关
12 1 1 1 1 2 1
西安航空职业技术学院 《智能系统设计与项目实践》
(课程补考论文)
论文题目: 六路抢答器
所属系部: 自动化工程学院
开课学期: 2014-15-2 补考学期: 2015-16-1
学生姓名: 刘欢 学 号: 13604103
专 业:
自动化工程学院
28