|
测试环境 M32L F=7.3728M
#include<iom32v.h>
#include<macros.h>
#include<stdio.h>
typedef unsigned char u08;
typedef unsigned int u16;
u08 SD2K_TWI (u08 SLA,u08* data, u08 nSize);
/* SD2K常用命令宏定义 */
/*====================================================/
功能描述: 复位实时时钟SD2K(SD2000AP)
复位时间: 00年, 01月, 01天, 0星期, 00时, 00分, 00秒
返 回 值: 0=复位成功 !0=失败
/====================================================*/
/*====================================================/
功能描述: 设置实时时钟SD2K(SD2000AP)新的日期和时间
入口参数:
返 回 值: 0=设置成功 !0=失败
/====================================================*/
/*====================================================/
功能描述: 读出实时时钟SD2K(SD2000AP)的日期和时间
入口参数:
返 回 值: 0=设置成功 !0=失败
/====================================================*/
/*====================================================/
功能描述: 读实时时钟SD2K(SD2000AP)的状态寄存器
入口参数:
返 回 值: 0=设置成功 !0=失败
/====================================================*/
/*====================================================/
功能描述: 写实时时钟SD2K(SD2000AP)的状态寄存器
入口参数:
返 回 值: 0=设置成功 !0=失败
/====================================================*/
/* TWI波特率计算 */
/*************************************************************************/
/* 设置 TWPS=0 即与分频系数为1 */
#define F_TWI 100000
///* 100KHz */
#define F_CPU 7372800
#define TWBR_SELECT 0x40
/* 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脚)
/****************************************************************************
TWI State codes
****************************************************************************/
// General TWI Master staus codes
#define TWI_START 0x08 // START has been transmitted
#define TWI_REP_START 0x10 // Repeated START has been transmitted
#define TWI_ARB_LOST 0x38 // Arbitration lost
// TWI Master Transmitter staus codes
#define TWI_MTX_ADR_ACK 0x18 // SLA+W has been tramsmitted and ACK received
#define TWI_MTX_ADR_NACK 0x20 // SLA+W has been tramsmitted and NACK received
#define TWI_MTX_DATA_ACK 0x28 // Data byte has been tramsmitted and ACK received
#define TWI_MTX_DATA_NACK 0x30 // Data byte has been tramsmitted and NACK received
// TWI Master Receiver staus codes
#define TWI_MRX_ADR_ACK 0x40 // SLA+R has been tramsmitted and ACK received
#define TWI_MRX_ADR_NACK 0x48 // SLA+R has been tramsmitted and NACK received
#define TWI_MRX_DATA_ACK 0x50 // Data byte has been received and ACK tramsmitted
#define TWI_MRX_DATA_NACK 0x58 // Data byte has been received and NACK tramsmitted
// TWI Slave Transmitter staus codes
#define TWI_STX_ADR_ACK 0xA8 // Own SLA+R has been received; ACK has been returned
#define TWI_STX_ADR_ACK_M_ARB_LOST 0xB0 // Arbitration lost in SLA+R/W as Master; own SLA+R has been received; ACK has been returned
#define TWI_STX_DATA_ACK 0xB8 // Data byte in TWDR has been transmitted; ACK has been received
#define TWI_STX_DATA_NACK 0xC0 // Data byte in TWDR has been transmitted; NOT ACK has been received
#define TWI_STX_DATA_ACK_LAST_BYTE 0xC8 // Last data byte in TWDR has been transmitted (TWEA = ??; ACK has been received
// TWI Slave Receiver staus codes
#define TWI_SRX_ADR_ACK 0x60 // Own SLA+W has been received ACK has been returned
#define TWI_SRX_ADR_ACK_M_ARB_LOST 0x68 // Arbitration lost in SLA+R/W as Master; own SLA+W has been received; ACK has been returned
#define TWI_SRX_GEN_ACK 0x70 // General call address has been received; ACK has been returned
#define TWI_SRX_GEN_ACK_M_ARB_LOST 0x78 // Arbitration lost in SLA+R/W as Master; General call address has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_ACK 0x80 // Previously addressed with own SLA+W; data has been received; ACK has been returned
#define TWI_SRX_ADR_DATA_NACK 0x88 // Previously addressed with own SLA+W; data has been received; NOT ACK has been returned
#define TWI_SRX_GEN_DATA_ACK 0x90 // Previously addressed with general call; data has been received; ACK has been returned
#define TWI_SRX_GEN_DATA_NACK 0x98 // Previously addressed with general call; data has been received; NOT ACK has been returned
#define TWI_SRX_STOP_RESTART 0xA0 // A STOP condition or repeated START condition has been received while still addressed as Slave
// TWI Miscellaneous status codes
#define TWI_NO_STATE 0xF8 // No relevant state information available; TWINT = ??
#define TWI_BUS_ERROR 0x00 // Bus error due to an illegal START or STOP condition
//*************************************************************************/
//#endif
u08 invert(u08 tdata);
/**********************************************************************?/
功能描述: 实时时钟SD2K的MEGA8 TWI访问程序
入口参数: SAL 操作指令
data 操作数据指针
nSize 操作数据大小
返 回 值: 0=操作成功 非0=操作失败(错误信息参MEGA8手册TWI模式状态字)
作 者:
最后修改: 2005-12-15
/ ***********************************************************************/
u08 SD2K_TWI(u08 SLA,u08* data, u08 nSize)
{
u08 dd;
// 设置TWI波特率 //
TWBR = TWBR_SELECT;
// 发送START信号,等待TWIT=1 //
TWCR = (1<<TWSTA) | (1<<TWEN)|(1<<TWINT);
while(!(TWCR & (1<<TWINT)));
// START信号成功发送了吗?不成功返回相应错误信息 //
if ((TWSR&0xf8) != TWI_START)
{printf("not start
");
return (TWSR&0xf8);
}
// 发送命令,等待发送完成 //
TWDR = SLA;
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)));
// 命令成功发送(或寻址成功)了吗?不成功返回相应错误信息 //
if (SLA & 0x01) // 1=读命令(主控接收器) 0=写命令(主控发送器)
{
if ((TWSR&0xf8) != TWI_MRX_ADR_ACK)
{printf("no read ack");
goto stoptwi;
// return TWI_MRX_ADR_ACK;
}
}
else
{
if ((TWSR&0xf8) != TWI_MTX_ADR_ACK)
{
printf("no write ack");
goto stoptwi;
//return TWI_MTX_ADR_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)));
*data = invert(TWDR);
// 数据接收成功 //
if (nSize ==1)
// 最后字节成功接收 不成功返回相应错误信息 //
{ if ((TWSR&0xf8 )!= TWI_MRX_DATA_NACK)//TWI_MRX_ADR_ACK )//TWI_MRX_DATA_ACK)
{ //return TWI_MRX_DATA_ACK;
printf("no ack1");
goto stoptwi;
}
}
else
// 非最后字节成功接收 不成功返回相应错误信息 //
{ if ((TWSR&0xf8) != TWI_MRX_DATA_ACK)
{//return TWI_MRX_DATA_ACK;
printf("no ack2");
goto stoptwi;
}
}
// 保存接收数据 //
// *data = TWDR;//invert(TWDR);
data++;
}while ( --nSize != 0 ); // 循环发送完
}
else //0=主控发送器操作
{
do {
// 准备送数据,发送,等待发送完成 //
TWDR = invert(*data);
TWCR = (1<<TWINT )| (1<<TWEN);
data++;
while (!(TWCR & (1<<TWINT)));
// 数据发送成功?不成功返回相应错误信息 //
if ((TWSR&0xf8) != TWI_MTX_DATA_ACK)
{ //return TWI_MTX_DATA_ACK;
printf("no send ack");
goto stoptwi;
}
}while ( --nSize != 0 ); // 循环发送完
}
}
stoptwi:
// 发送STOP信号//
TWCR = (1<<TWINT )|( 1<<TWSTO) |( 1<<TWEN);
while ( (TWCR & (1<<TWSTO)) !=0 );
TWCR = 0;
// 调整端口设置,设置为高电平输出 //
DDRC |= 3;
// 成功发送完毕,返回0 //
return 0;
}
u08 invert(u08 tdata)
{
u08 k,p,l,m=0;
p=0x01;
l=0x01;
for(k=0;k<=7;k++)
{
if(p&tdata){m=m|l;}
if(k!=7)m=m<<1;
p=p<<1;
}
m&=0x7f;
return m;
}
void BCD2HEX(u08 *buf)
{
u08 t,m;
m=*buf;
t=(m&0x0f)+((m&0xf0)>>4)*10;
*buf=t;
}
void Port_init(void)
{
PORTA = 0x00;
DDRA = 0xFF;
PORTB = 0x00;
DDRB = 0xFF;
PORTC = 0xff;
DDRC = 0xFF;
PORTD = 0x04;
DDRD = 0xF0;
//在16L中也试过类试的现象,后来把INT0置为输入口,用上升沿时设输入为高阻,
//外部加对地下拉,用下降沿时设输入上拉,问题解决。
}
void USART_init(void)
{
//UBRRH=0;
//UBRRL=38;
//UCSRC=0x18;
UCSRB = 0x00; //disable while setting baud rate
UCSRA = 0x00;
UCSRC = BIT(URSEL) | 0x06;
UBRRL = 0x0b; //set baud rate lo 0x2F FOR 9600/0x11 for 38400
UBRRH = 0x00; //set baud rate hi
UCSRB = 0x18;
}
void ExtPort_init(void)
{
// DDRA= 0xFF;
// PORTA = 0x00;
// ' put zero's on relays-port
//Latch_H;
//Latch_L;
return;
}
//uchar 7 6 5 4 3 2 1 0
// – – – WDTOE WDE WDP2 WDP1 WDP0 WDTCR
//Read/Write R R R R/W R/W R/W R/W R/W
//Initial Value 0 0 0 0 0 0 0 0
void WDT_init(void)
{
//
/* reset WDT */
_WDR();
/* Write logical one to WDTOE and WDE */
//WDTCR |= (1<<WDTOE) | (1<<WDE);
WDTCR=0X18; //现在把WDTCH给关掉了
/* Turn off WDT */
WDTCR = 0x00;
//WDTCR=0X17;
}
/*********延时子程序*********/
void delay_us(unsigned int dt)
{
while(dt)
dt--;
asm("nop");
}
void delay_1ms(void) //1ms
{
unsigned int i;
for(i=1;i<1142;i++)
;
}
void delay_ms(unsigned int n)
{
unsigned int i=0;
while(i<n)
{
delay_1ms();
i++;
}
}
/****************************************************************************
Call this function to set up the TWI master to its initial standby state.
Remember to enable interrupts from the main application after initializing the TWI.
****************************************************************************/
void TWI_Master_Initialise(void)
{
TWBR = TWBR_SELECT ; // Set bit rate register (Baudrate). Defined in header file.
// TWSR = TWI_TWPS; // Not used. Driver presumes prescaler to be 00.
TWDR = 0xFF; // Default content = SDA released.
TWCR = (1<<TWEN)| // Enable TWI-interface and release TWI pins.
(0<<TWIE)|(0<<TWINT)| // Disable Interupt.
(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)| // No Signal requests.
(0<<TWWC); //
}
void main(void)
{
u08 a1[11],d,s;
WDT_init();
Port_init();
USART_init();
ExtPort_init();
GICR=0X00;//Enable Int0
MCUCR=0X00;//int0 rising edge
//Int0flag=0x00;
SREG|=0X80; //2005
TWI_Master_Initialise();
printf("----------------------------
");
while(1)
{
s= SD2K_TWI(CMD_STUSR_R, &d, 1);//0x62
printf("=%d ",s);
SD2K_TWI(CMD_TIME_R, &a1[0], 3);
for(s=0;s<3;s++)BCD2HEX(&a1);
printf("hh:mm:ss=%d:%d:%d
",a1[0],a1[1],a1[2]);
SD2K_TWI(CMD_TIMEALL_R, &a1[0], 7);
for(s=0;s<7;s++)BCD2HEX(&a1);
printf("yy:mm:dd: -d- hh:mm:ss=%d:%d:%d -%d- %d:%d:%d
",a1[0],a1[1],a1[2],a1[3],a1[4],a1[5],a1[6]);
delay_ms(800);
printf("----------------------------
");
}
} |
|