网站公告列表

  没有公告

加入收藏
设为首页
联系站长
您现在的位置: 61IC中国电子在线 >> 技术文库 >> 嵌入式 >> 文章正文
  用gcc3.3写的MEGA8 TWI访问实时时钟SD2000的程序           ★★★ 【字体:
用gcc3.3写的MEGA8 TWI访问实时时钟SD2000的程序
作者:61IC录入    文章来源:本站原创    点击数:    更新时间:2006-4-7    
这是我写的使用mega8 的twi访问sd2000实时时钟的程序,稍加修改可用于访问24xx.
/********************************************************************** /
功能描述: 实时时钟SD2K的MEGA8 TWI访问程序
入口参数:     SAL        操作指令
            data    操作数据指针
            nSize    操作数据大小        
返 回 值: 0=操作成功 非0=操作失败(错误信息参MEGA8手册TWI模式状态字)
作      者: 程志宏
最后修改: 2003-04-09
/ ***********************************************************************/
u08 SD2K_TWI (u08 SLA,u08* data, u08 nSize)
{    
    // 关闭显示 //
    LED_DX_CTL(0x1f);    //关闭段显,全部高阻输入(包括PD5-7,PB0_4)
    LED_WX_CTL(0x04);    //关闭位显,全部为高电平输出
    
    // 调整端口设置,设置为上拉输入 //
    DDRC &= ~(1<<PC5 | 1<<PC4);
    
    // 设置TWI波特率 //
    TWBR = TWBR_SELECT;
    
    // 发送START信号,等待TWIT=1 //
    TWCR = 1<<TWSTA | 1<<TWEN;            
    while (!(TWCR & (1<<TWINT)));
    
    // START信号成功发送了吗?不成功返回相应错误信息 //
    if (TWSR != TW_START) return TW_START;
    
    // 发送命令,等待发送完成 //
    TWDR = SLA;
    TWCR = 1<<TWINT | 1<<TWEN;
    while (!(TWCR & (1<<TWINT)));
    
    // 命令成功发送(或寻址成功)了吗?不成功返回相应错误信息 //
    if (SLA & 0x01)        // 1=读命令(主控接收器)  0=写命令(主控发送器)
        { if (TWSR != TW_MR_SLA_ACK) return TW_MR_SLA_ACK; }
    else
        { if (TWSR != TW_MT_SLA_ACK) return TW_MT_SLA_ACK; }
        
    // 传送字节数!=0 ?//
    if (nSize !=0)
    {
        if (SLA & 0x01)        // 1=主控接收器操作  
            {    
            do    {
                // 若准备接收最后一个字节发送则发NACK,否则发送ACK //
                if (nSize ==1)
                    { TWCR = 1<<TWINT | 1<<TWEN; } //准备发送NACK
                else
                    { TWCR = 1<<TWINT | 1<<TWEA | 1<<TWEN; } //准备发送ACK
                
                // 等待接收完成 //
                while (!(TWCR & (1<<TWINT)));    
            
                // 数据接收成功? //
                if (nSize ==1)
                    // 最后字节成功接收? 不成功返回相应错误信息 //
                    { if (TWSR != TW_MR_DATA_NACK) return TW_MR_DATA_NACK;}
                else
                    // 非最后字节成功接收? 不成功返回相应错误信息 //
                    { if (TWSR != TW_MR_DATA_ACK) return TW_MR_DATA_ACK;}  

                // 保存接收数据 //
                *data = invert(TWDR);
                data++;
                    
                }while ( --nSize != 0 );    // 循环发送完
            }                        
            
        else                //0=主控发送器操作
            {        
            do    {
                // 准备送数据,发送,等待发送完成 //
                TWDR = invert(*data);
                TWCR = 1<<TWINT | 1<<TWEN;
                data++;
                while (!(TWCR & (1<<TWINT)));
    
                // 数据发送成功?不成功返回相应错误信息 //
                if (TWSR != TW_MT_DATA_ACK) return TW_MT_DATA_ACK;
                    
                }while ( --nSize != 0 ); // 循环发送完
            }
    }
        
    // 发送STOP信号//
    TWCR = 1<<TWINT | 1<<TWSTO | 1<<TWEN;
        
    while ( (TWCR & (1<<TWSTO)) !=0 );    
    TWCR = 0;        
    
    // 调整端口设置,设置为高电平输出 //
    DDRC |= 1<<PC5 | 1<<PC4;
    
    // 成功发送完毕,返回0 //
    return 0;
}

头文件sd2k.h内容:

#ifndef SD2K_H
#define SD2K_H

/* 实时时钟用全局变量外部申明 */
/*************************************************************************/
extern u08 volatile g_sd2k_stusr;            //实时时钟状态寄存器缓存区
extern u08 volatile g_sd2k_return;            //实时时钟操作返回信息

extern u08 volatile g_sd2k_read_time [7];    //实时时钟读取时间缓存区
extern u08 volatile g_sd2k_set_time[7];     //实时时钟设置时间缓存区

extern u16 volatile g_sd2k_show_time[4] ;     //时间显示缓存区:年,月日,时分,分秒


/* 函数外部申明 */
/*****************************************************/
extern void SD2K_SHOW_TIME(u08* source_time, u08* show_time);
extern u08 SD2K_TWI (u08 SLA,u08* data, u08 nSize);


/* SD2K常用命令宏定义 */
/*====================================================/
功能描述: 复位实时时钟SD2K(SD2000AP)
复位时间: 00年, 01月, 01天, 0星期, 00时, 00分, 00秒
返 回 值: 0=复位成功 !0=失败
/====================================================*/
#define SD2K_RESET()    g_sd2k_return=SD2K_TWI(CMD_RESET, &g_sd2k_stusr, 0)

/*====================================================/
功能描述: 设置实时时钟SD2K(SD2000AP)新的日期和时间
入口参数: g_sd2k_set_time
返 回 值: 0=设置成功 !0=失败
/====================================================*/
#define SD2K_SET_TIME(x) g_sd2k_return=SD2K_TWI(CMD_TIMEALL_W,(x), 7)

/*====================================================/
功能描述: 读出实时时钟SD2K(SD2000AP)的日期和时间
入口参数: g_sd2k_real_time
返 回 值: 0=设置成功 !0=失败
/====================================================*/
#define SD2K_READ_TIME(x) g_sd2k_return=SD2K_TWI(CMD_TIMEALL_R,(x), 7)

/*====================================================/
功能描述: 读实时时钟SD2K(SD2000AP)的状态寄存器
入口参数: g_sd2k_real_time
返 回 值: 0=设置成功 !0=失败
/====================================================*/
#define SD2K_READ_STUSR() g_sd2k_return=SD2K_TWI (CMD_STUSR_R, &g_sd2k_stusr, 1)

/*====================================================/
功能描述: 写实时时钟SD2K(SD2000AP)的状态寄存器
入口参数: g_sd2k_real_time
返 回 值: 0=设置成功 !0=失败
/====================================================*/
#define SD2K_WRITE_STUSR() g_sd2k_return=SD2K_TWI (CMD_STUSR_W, &g_sd2k_stusr, 1)



/* TWI波特率计算 */
/*************************************************************************/
//#define F_CPU            4000000             /* 4MHz processor */
/* 设置 TWPS=0 即与分频系数为1 */
#define F_TWI             100000                /* 100KHz */
#define TWBR_SELECT        (((F_CPU/F_TWI)-16)/2)

/* SD2K命令定义 */
/*************************************************************************/  
#define CMD_RESET        0x61        // 复位命令,60也可以

#define CMD_STUSR_W        0x62        // 写状态寄存器指令
#define CMD_STUSR_R        0x63        // 读状态寄存器指令

#define CMD_TIMEALL_W    0x64        // 写实时时钟数据指令(年.月.日.星期.时.分.秒)
#define CMD_TIMEALL_R    0x65        // 读实时时钟数据指令(年.月.日.星期.时.分.秒)

#define CMD_TIME_W        0x66        // 写实时时钟数据指令(时.分.秒)
#define CMD_TIME_R        0x67        // 读实时时钟数据指令(时.分.秒)

#define CMD_INT1_W        0x68        // 写频率事件设置指令(INT1脚)
#define CMD_INT1_R        0x69        // 读频率事件设置指令(INT1脚)

#define CMD_INT2_W        0x6A        // 写频率事件设置指令(INT2脚)
#define CMD_INT2_R        0x6B        // 读频率事件设置指令(INT2脚)

/*************************************************************************/
#endif
有益的提示:
  注意sd200访问时序,和24xx读写有较大不同
1。sd2000的访问时序和常用的IIC设备如24CXX有较大不同,SD2000发完命令(相当于24CXX的器件地址)后,就直接开始连续读写了(复位命令后无数据)。而24XX再发完命令后还要发读写地址,如果是写,还要重发START信号,请注意这些不同!
2。特别还要注意,SD2000的数据是低位在先的(命令还是高位在先的),所以收得的数据或发出的数据要处理一下(字节颠倒),而通常大部分IIC设别从头到尾都是高位在先的。
3。最后还要注意以下时序的周期,SD2000最大速率为100K,也就是CLK信号的周期,周期为10us,所以要注意CLK保持高/低电平的时间要>5us,时间长点或长很多是没有问题的。
    如果能搞明白sd2000和24xx的访问时序的不同,那将上面的程序修改作访问24xx,因该很简单吧!
               欢迎点击进入:TI德州中文网   (国内唯一针对TI应用的中文技术网站)    文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    没有相关文章
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    站长:61IC 湘ICP备05002478号