精美模拟/数字时钟在MP3等数码产品中的应用

精美模拟/数字时钟在MP3等数码产品中的应用
作者:hyzxb
目录
前言
S-35380A的特性
I2C总线
设计需求
时钟模块功能
模拟时钟显示功能
流程图
附录:源程序
结束语
前言
  随着数码产业的蓬勃发展,出现了越来越多的数码产品如MP3、PMP、数码相机等。如何使自己的产品具有特色,吸引顾客的眼球,创新是必不可少的。
  本文尝试在当今较流行的某MP3方案中增加时钟功能 ,实现精美的数字、模拟时钟显示、闹铃自动开机和报警提醒等功能,使用户能更进一步感受人性化的设计,体验数码快乐。
S-35380A的特性
S-35380A是可以在超低消耗电流、宽工作电压范围内工作的2线CMOS实时时钟IC。工作电压为1.3 V ~ 5.5 V,可适用于从主电源电压开始到备用电源电压驱动为止的宽幅度的电源电压。通过0.25 µA的计时消耗电流和1.1 V计时工作电压,可大幅度地改善电池的持续时间。使用备用电池工作的系统,可将内置于实时时钟的自由寄存器作为用户备用存储器功能来使用。因为此用户寄存器的电源电压可保持在1.2 V(最小值),存储在寄存器的主电源切断前的情报,在电压恢复后的任何时候均可读出。
产品因为内置了时钟调整功能,所以可以在很宽的范围内校正石英的频率偏差,能以最小分解能力 = 1 ppm来进行校正。接着,通过此功能和温度传感器的组合,可设定适应温度变化的时钟调整值,针对温度偏差亦可实现高精度的计时功能。
特点
• 低消耗电流 : 0.25 A 典型值 (VDD 3.0 V,Ta 25C)
• 宽工作电压范围 : 1.3 V  5.5 V
• 最低计时工作电压 : 1.1 V
• 内置时钟调整功能
• 内置用户自由寄存器
• 2线(I2C-BUS)方式的CPU界面
• 内置报警中断器
• 内置电源切断以及电源接通时的标记生成电路
• 内置到2099年为止的自动日历,润年自动运算功能
• 内置稳压电路
• 内置32 kHz石英振荡电路(Cd内置,Cg外接)
• 封装 : 8-Pin SOP(JEDEC),8-Pin TSSOP
用途
• 数码相机
• 数码摄像机
• 电子式电力测量仪(数字式电力表)
• DVD录像机
• 电视,录像机
• PHS
• 携带电话
• 汽车导航

1. 通信数据构成
为了进行通信,在系统上的主装置针对从属装置,使之产生开始状态。接着,从SDA线路上传送出4位长的装置地址、3位长的指令和1位长的读出/写入指令。在装置地址上的上位4位称为装置码,固定为“0110”。

2. 指令构成
指令有8 种,通过指令可以进行各种寄存器的读出/写入。
3引脚说明



I2C总线
I2C简介
Inter-IC(I2C)总线是由飞利浦半导体公司20年前开发并推出的,是一种具有多端控制能力的双线双向串行数据总线系统。对于嵌入式系统设计者来说,有以下好处:
•        更少的管脚连接,也就不需要并行总线接口。
•        由更少的管脚连接带来的更小的电路规模。
•        更少的电路板层数和更少的电路连线。
•        由于I2C支持多主控,所以更容易调试。
支持I2C的设备有微控制器,A/D、D/A转换器,储存器,LCD控制器,LED驱动器,I/O端口扩展器以及实时时钟。
I2C的性能
标准I2C总线传输速率可以到100Kbit/s,通过使用了7位地址码,就能支持128个设备。加强型I2C总线用了10位地址码(能够支持1024个设备),快速模式(400Kbit/s)和高速模式(最高有3.4Mbit/s)。I2C是多主控总线,所以任何一个设备都能像主控器一样工作,并控制总线。总线上每一个设备都有一个独一无二的地址,根据设备它们自己的能力,它们可以作为发射器或接收器工作。多路微控制器能在同一个I2C总线上共存。只要很小的电路附件,I2C总线就能够支持设备在不同电平下工作(例如:3.3伏和5伏),
I2C总线的工作情况
I2C总线的规范中规定了如何在两个设备之间传递数据,采取的方法是总线仲裁、时钟同步和总线的电气特征。在一次数据传输中,一个设备扮演临时主控器,开始在它和一个有单一地址设备(从控器)之间的传输。主控器为数据传输产生时钟信号。规范中要求数据线(SDA,串行数据线)只有在时钟(SCL,串行时钟线)处于低平时才能变化。
总线的一次典型工作流程如下:
1.开始:信号表明传输开始。
2.地址:主设备发送地址信息,包含7位的从设备地址和1位的指示位(表明读或者写,即数据流的方向)。
3.数据:根据指示位,数据在主设备和从设备之间传输。数据一般以8位传输,最重要的位放在前面;具体能传输多少量的数据并没有限制。接收器上用一位的ACK(回答信号)表明每一个字节都收到了。传输可以被终止和从新开始。
4.停止:信号结束传输。
实时时钟s-35380A的工作时序

s-35380A是采用I2C-BUS方式的串行接口来接受各种指令,进行数据的读出写入。

1. 开始状态
SCL线路处于“H”电位时,通过SDA线路从“H”变为“L”,变为开始状态。全部的工作从开始状态开始。

2. 停止状态
SCL线路处于“H”电位时,通过SDA线路从“L”变为“H”,变为停止状态。在读出时序时,一接收到停止状态,读出工作就被中断,装置变为待机模式。

3. 数据传送
在SCL线路为“L”电位之时,通过使SDA线路产生变化,进行数据传送。
在SCL线路为“H”电位之时, SDA线路一发生变化,开始或者停止状态就会被认识。

4. 确认
数据传送可连续传送8位。接着,在第9个的时钟周期期间,接收数据的系统总线上的装置设置SDA线路为“L”,反馈回接收了数据的确认信号。

5. 数据读出
从外部进行开始状态的检测后,接收装置码以及指令。这时,读出写入位为“1”时,变为数据读出模式。数据输出顺序从LSB开始输出。

6. 数据写入
从外部进行开始状态的检测后,接收装置码以及指令。这时,读出写入位为“0”时,变为实时数据写入模式或者变为其他寄存器的写入模式。无论是实时数据写入模式、还是状态寄存器写入模式,它们的数据输入顺序都从LSB开始。

数据存取时序图示例



7. INT1寄存器_1存取、INT1寄存器_2存取
INT1寄存器_1的写入/读出,数据因状态寄存器_2的设定的不同而异,所以请务必在状态寄存器_2的设定后,再进行INT1寄存器_1的写入/读出。状态寄存器_2在报警设定时为3字节的报警时刻数据寄存器,其他情况下为1字节的寄存器,在选择频率稳态中断设定时,变为频率占空设定数据。
注意 不能使报警数据和频率占空数据同时发生作用,务请注意。

8.应用电路


设计需求
   根据设计需要,我们需要在MP3播放器中增加如下功能:
1 模拟时钟的显示;
  要求能在播放和不播放MP3音乐时,用户能随时弹出精美的模拟时钟,并能从屏幕上显示出如年、月、日、星期、时间等时间信息。
2 时间的设定;
  用户可以根据需要调整时间,并能保存所设定的时间(不存在的时间除外)。
3 定时闹钟报警的设定
  用户可根据需要自己设定闹钟报警时间,并能保存所设定的报警时间数据。
4 蜂鸣器报警输出
  当RTC时间到达所设定的报警时刻时,无论是在开机或关机的情况下,MP3播放器都将驱动蜂鸣器报警。关机时将能自动开机并报警。
5 对系统的影响
RTC模块的加入不能对系统造成不良的影响,如增大功耗或降低系统的稳定性等。
时钟模块功能
  根据设计需求,可以将时钟模块划分成以下功能模块:
模拟时钟的显示模块;
时钟数据的存取模块;
报警设定模块;
时间设定模块;
报警驱动输出模块;
模拟时钟显示功能
编程思路
  考虑到需要在LCD屏幕上以模拟表的形式实时地显示当前时间,因此时钟显示模块主要分两部分:
数字时钟数据的读取;
  根据I2C总线的通信协议,建立底层的I2C通信机制,并完成对RTC的数据实时存取,将获得的时间数据存入特定的变量中保存。
模拟时钟的实时绘制;
  时钟数据的获取比较容易实现,然而要实现以模拟表的形式在LCD上显示出来,却不是一件容易的事情。
主要存在以下技术难点:
1 现有的MP3方案没有提供图形绘制的接口,需要自己独立完成;
2 在图形绘制中需要牵涉三角函数计算;
3 时、分、秒表针如何实现实时动态显示;

模拟时钟显示模块的开发步骤

1获取时钟实时数据,并将其存在RTCYear、RTCMonth、RTCDay、RTCWeek、RTCHours、RTCMinutes、RTCSeconds中保存。

2建立绘图API库函数graphicslib.h,包括:
void _reentrant SetPixel(int x, int y);
void _reentrant DrawLine(int x1, int y1, int x2, int y2);
void _reentrant DrawCircle(int CenterX, int CenterY, int Radius);
void _reentrant DrawCirclePlotPoints(int CenterX, int CenterY, int x,int y);
void _reentrant DrawBox(int Ax, int Ay, int Bx, int By, int penWidth);
void _reentrant fill(Cpoint *pt, int i);
void _reentrant Polygon(Cpoint *point,int num);

3模拟表的实现
1)        秒指针定位
由于要求显示秒表指针,因此秒数据的显示位置(X,Y)采用查表的方式在LCD上定好,这样可以省略计算过程,节省了时间。秒指针是用DrawLine(int x1, int y1, int x2, int y2)函数来简单实现的。
2)        制作正弦、余弦三角函数表
通过查表可以大大加速处理速度,体现显示的实时性。
3)        时、分指针的定位及绘制
主要由以下几个函数来实现:
a函数GetHandPoints(int nValue, int type, Cpoint* pPoints,int minutes)
入口参数:
int nValue:接收到的时钟数据,在RTCSeconds 、RTCMinutes、RTCHours中取值;
int type:时、分指针类型选择;
int minutes:分数据,时针的位置是由分数据决定的。
出口参数:
Cpoint* pPoints:指针的位置点,一个表指针有四个顶点。
函数说明:
该函数主要是将接收到的时钟数据按类型进行计算,得到表指针的四个顶点的坐标,并将其保存在四维的pPoints数组中。

void _reentrant GetHandPoints(int nValue, int type, Cpoint* pPoints,int minutes)
{
  double ratio = 0;
  switch (type)
  {
    case HOUR:
    {
      //hour hand goes out to 50% of the radius
      ratio = 0.6;
      
      //Convert the hour angle (0 - 11) to a minute value (0 - 59)
      //for drawing, then adjust for a gradual transition from hour to hour
      nValue *= 5;
      nValue += (minutes / 12);
      
      break;
    }
    case MINUTE:
    {
      //Minute hand goes out to 70% of the radius
      ratio = 0.8;
      break;
    }
   
    default:
    {
      
      break;
    }
  }
    pPoints[0] = ComputePoint(nValue+30, 0.1);
    pPoints[1] = ComputePoint(nValue+15, 0.05);
    pPoints[2] = ComputePoint(nValue,    ratio);
    pPoints[3] = ComputePoint(nValue-15, 0.05);  
}

b 函数Cpoint _reentrant ComputePoint(int nMinute, double ratio)
入口参数:
int nMinute:接收到的时钟数据,在RTCMinutes、RTCHours中取值;
double ratio:表指针顶点到原点的距离比例因子选择;
出口参数:
Cpoint pt:表指针的顶点坐标,一个表指针有四个顶点。
函数说明:
该函数主要是将接收到的时钟数据进行计算,得到表指针的一个顶点的坐标,并将其保存在pt中。数组cos[]和sin[]事先存储0~60分钟时刻所代表的角度的正、余弦三角函数值。
表达式:
pt.x = CLOCK_CENTER_X + (int) (RADIUS*ratio*cos[nMinute] + 0.5);
pt.y = CLOCK_CENTER_Y + (int) (RADIUS*ratio*sin[nMinute] + 0.5);
是将表指针某一个顶点转化成直角坐标值(x,y),因为一个表指针有四个顶点,并且四个顶点到原点的距离有一个ratio。

Cpoint _reentrant ComputePoint(int nMinute, double ratio)
{
  Cpoint pt;
   pt.x = CLOCK_CENTER_X + (int) (RADIUS*ratio*cos[nMinute] + 0.5);
  pt.y = CLOCK_CENTER_Y + (int) (RADIUS*ratio*sin[nMinute] + 0.5);
  return pt;
}

c 函数void _reentrant DrawHand(int value, int handtype,int minute)
入口参数:
int value:接收到的时钟数据,在RTCMinutes、RTCHours中取值;
int handtype:时、分指针类型选择;
int minute:分数据,时针的位置是由分决定的。
出口参数:
无。
函数说明:
该函数主要是将接收到的时钟数据进行计算,得到表指针的顶点的坐标,并根据顶点坐标值绘制出表指针。
void _reentrant DrawHand(int value, int handtype,int minute)
{
  Cpoint Points[4];
  GetHandPoints(value, handtype, Points,minute);       
  //if (handtype == SECOND)
   // DrawLine(Points[0].x,Points[0].y,Points[1].x,Points[1].y);
  //else
    Polygon(Points,3);
  }

4)        绘制模拟表盘
绘制模拟表盘的函数为DrawClockFace(),由于指针会破坏表盘,因此需要实时刷新。

5)        实时绘制表针
实时绘制表针是通过函数DrawHandS()来实现的,该函数通过当前的时钟数据与上一次的时钟数据进行比较,决定是否需要重新绘制表针,一般来说秒针是需要实时刷新重绘的。该函数要大量调用绘图API函数,秒针的绘制是通过简单调用DrawLine函数来实现的。
void _reentrant DrawHandS()
{
         //if(oldSeconds !=  RTCSeconds || iUpdateTime != 0)
         {
                       
                //SysPostMessageWithChecking(5,LCD_PRINT_RANGE_RSRC,33,36,RSRC_GENESEE_BMP);
               
                drawType = PIXEL_OFF;
                DrawLine(CLOCK_CENTER_X, CLOCK_CENTER_Y, x_coords[oldSeconds], y_coords[oldSeconds]);
                //DrawHand(RTCHours, HOUR,oldMinutes);
               
                drawType = PIXEL_ON;
                DrawLine(CLOCK_CENTER_X, CLOCK_CENTER_Y, x_coords[RTCSeconds], y_coords[RTCSeconds]);         
                DrawHand(RTCMinutes, MINUTE,RTCMinutes);
                DrawHand(RTCHours, HOUR,RTCMinutes);
               
                oldSeconds =  RTCSeconds;
               
                if(oldMinutes !=  RTCMinutes || iUpdateTime != 0)
                {       
                        drawType = PIXEL_OFF;
                        DrawHand(oldMinutes, MINUTE,oldMinutes);
                        //DrawHand(RTCHours, HOUR,oldMinutes);
                       
                        drawType = PIXEL_ON;
                        DrawHand(RTCMinutes, MINUTE,RTCMinutes);
                        DrawHand(RTCHours, HOUR,RTCMinutes);
                       
                        //oldMinutes =  RTCMinutes;
                       
                        if(oldHours !=  RTCHours || iUpdateTime != 0||(RTCMinutes%12==0) )
                        {                                       
                                drawType = PIXEL_OFF;
                                DrawHand(oldHours, HOUR,oldMinutes);
                               
                                drawType = PIXEL_ON;
                                DrawHand(RTCHours, HOUR,RTCMinutes);
                                DrawHand(RTCMinutes, MINUTE,RTCMinutes);
                               
                                oldHours =  RTCHours;
                        }
                        oldMinutes =  RTCMinutes;
                 }
                iUpdateTime = 0;
         }
}

流程图
1 RTC初始化

结束语
本文的设计已成功应用于某款MP3样机上,效果非常理想。由于采用C语言编程,本文的方案可以很方便地移植到其他数码产品的方案中,具有极强的应用价值。

设计应用实例:
http://news.sanhaostreet.com/NewsData/2005/4/20054191612207241.shtml
在欣赏音乐同时实现模拟、数字时钟切换显示;
闹铃开机提醒;
定时报警闹铃;

如果增加内置扬声器,结合时钟功能可以有更强大的功能哦,如:可以增加一个和弦音乐芯片可实现音乐定时开机闹铃;或者将存在FLASH里的MP3歌曲/录制的语音文件做为闹铃通过扬声器定时输出,这样你可以在美妙的音乐中开始新的一天!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值