|
楼主 |
发表于 2012-3-29 13:37:27
|
显示全部楼层
哦,多谢您的提醒。
是这样的,我现在用stc的mcu与ds1305通讯,但通讯不成功,因为第一次使用,在stc的官网上下载了spi的通讯例子,结合ds1305通讯,但就是不成功,我现在正在调试stc的spi功能,拿示波器监测sclk,但我望SPDAT写入数据,sclk并没有变化,我选择的是主模式,下面是我的代码,请大家指导一下。
#include <8051.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "OCMJ4X8C.h"
#define BYTE unsigned char
#define WORD unsigned int
#define DWORD unsigned long
#define uchar unsigned char
__sfr AUXR = 0x8e; //Auxiliary register
__sfr SPSTAT = 0xcd; //SPI status register
__sfr SPCTL = 0xce; //SPI control register
__sfr SPDAT = 0xcf; //SPI data register
__sbit __at (0x80) SPIF; //SPSTAT.7
__sbit __at (0x40) WCOL; //SPSTAT.6
__sbit __at (0x80) SSIG; //SPCTL.7
__sbit __at (0x40) SPEN; //SPCTL.6
__sbit __at (0x20) DORD; //SPCTL.5
__sbit __at (0x10) MSTR; //SPCTL.4
__sbit __at (0x08) CPOL; //SPCTL.3
__sbit __at (0x04) CPHA; //SPCTL.2
__sbit __at (0x00) SPDHH; //CPU_CLK/4
__sbit __at (0x01) SPDH; //CPU_CLK/16
__sbit __at (0x02) SPDL; //CPU_CLK/64
__sbit __at (0x03) SPDLL; //CPU_CLK/128
/************************** Bit Declarations *******************************/
#define CS P3_6 /* to CE pin on DS1305 */
#define MOSI P1_5 /* to SDI & SDO pins on DS1305 */
#define MISO P1_6
#define SCLK P1_7 /* to SCLK pin on DS1305 */
/************************** Global Variables *******************************/
#define TRUE 0x01
#define FALSE 0x00
/**
* @brief Offset from read to write registers
*/
#define ds1305_REG_WRITE_OFFSET 0x80
/**
* @name Bases and offsets for the alarms
* @{
*/
#define ds1305_REG_ALARM0_BASE 0x07
#define ds1305_REG_ALARM1_BASE 0x0b
#define ds1305_REG_MINUTES_OFFSET 0x01
#define ds1305_REG_HOURS_OFFSET 0x02
#define ds1305_REG_DAY_OFFSET 0x03
/** @} */
/**
* @name Main calendar registers
* @{
*/
#define ds1305_REG_SECONDS 0x00
#define ds1305_REG_MINUTES 0x01
#define ds1305_REG_HOURS 0x02
#define ds1305_REG_DAY 0x03
#define ds1305_REG_DATE 0x04
#define ds1305_REG_MONTH 0x05
#define ds1305_REG_YEAR 0x06
/** @} */
/**
* @name Alarm0 registers
* @{
*/
#define ds1305_REG_SECONDS0 0x07
#define ds1305_REG_MINUTES0 0x08
#define ds1305_REG_HOURS0 0x09
#define ds1305_REG_DAY0 0x0a
/** @} */
/**
* @name Alarm1 registers
* @{
*/
#define ds1305_REG_SECONDS1 0x0b
#define ds1305_REG_MINUTES1 0x0c
#define ds1305_REG_HOURS1 0x0d
#define ds1305_REG_DAY1 0x0e
/** @} */
/**
* @name Other registers
* @{
*/
/** @brief Control Register */
#define ds1305_REG_CR 0x0f
/** @brief Status Register */
#define ds1305_REG_SR 0x10
/** @brief Trickle Charger Register */
#define ds1305_REG_TCR 0x11
/** @brief RAM register */
#define ds1305_REG_RAM 0x20
/** @} */
/**
* @name Control Register bits
* @{
*/
/** @brief Interrupt 0 enable @note Active high */
#define ds1305_BIT_AIE0 0
/** @brief Interrupt 1 enable @note Active high */
#define ds1305_BIT_AIE1 1
/** @brief Enable int0 pin for both interrupts */
#define ds1305_BIT_INTCN 2
/** @brief Write protect bit */
#define ds1305_BIT_WP 6
/** @brief Enable oscillator bit */
#define ds1305_BIT_EOSC 7
/** @} */
/**
* @name Status Register bits
* @{
*/
/** @brief Indicate interrupt 0 @note Active high */
#define ds1305_BIT_IRQF0 0
/** @brief Indicate interrupt 1 @note Active high */
#define ds1305_BIT_IRQF1 1
/** @} */
/**
* @name To specify 12/24h and AM/PM mode
* @{
*/
/** @brief Use !ds1305_24H for 12 hours mode */
#define ds1305_24H 0
/** @brief Use !ds1305_AM for PM */
#define ds1305_AM 0
/** @} */
/**
* @name To specify the alarms
* @{
*/
#define ds1305_ALARM0 0
#define ds1305_ALARM1 1
/** @} */
/**
* @name To specify the interrupts
* @{
*/
#define ds1305_INT0 0
#define ds1305_INT1 1
/** @} */
/**
* @name To specify the alarms intervals
* @{
*/
/** @brief Every seconds */
#define ds1305_ALARM_ONCE 15
/** @brief When seconds match */
#define ds1305_ALARM_SECOND 7
/** @brief When minutes & seconds match */
#define ds1305_ALARM_MINUTE 3
/** @brief When hours, minutes & seconds match */
#define ds1305_ALARM_HOUR 1
/** @brief When days, hours, minutes & seconds match */
#define ds1305_ALARM_DAY 0
/** @} */
/**
* @name ASCII format & errors
* @{
*/
/** @brief YYYY-MM-DD HH:MM:SS AM/PM */
#define ds1305_ASCII_FULL 0
/** @brief Format HH:MM:SS AM/PM */
#define ds1305_ASCII_TIME 1
/** @brief Format YYYY-MM-DD */
#define ds1305_ASCII_DATE 3
/** @brief Format : Day, HH:MM:SS AM/PM */
#define ds1305_ASCII_ALARM 4
/** @brief Error code string is empty */
#define ds1305_ASCII_EMPTY 10
/** @brief Error code string is too long */
#define ds1305_ASCII_TOO_LONG 11
/** @brief Error code string is too short */
#define ds1305_ASCII_TOO_SHORT 12
/** @brief Error code string is invalid */
#define ds1305_ASCII_INVALID 13
/** @brief Error code unknown */
#define ds1305_ASCII_UNDEFINED 255
/** @} */
typedef struct ds1305_time {
/** @brief 00 - 99 */
BYTE year;
/** @brief 01 - 12 */
BYTE month;
/** @brief 01 - 31 */
BYTE date;
/** @brief 1 - 7 */
BYTE day;
/** @brief 00 - 23 */
BYTE hours;
/** @brief 00 - 59 */
BYTE minutes;
/** @brief 00 - 59 */
BYTE seconds;
/** @brief Use @a ds1305_24H | @a !ds1305_24H */
BYTE format;
/** @brief Use @a ds1305_AM | @a !ds1305_AM */
char am_pm;
} ;
/*
BYTE utils_DecToBcd(BYTE number);
BYTE utils_BcdToDec(BYTE number);
BYTE spi_MasterTransmit(BYTE dat);
void spi_SlaveSelect (BYTE action);
void spi_MasterInit(void);
BYTE ds1305_WriteTimeAscii(char *string);
BYTE _strncpyx (char *dest, char *src, BYTE n, BYTE x);
BYTE _AsciiValidate(char *string);
void ds1305_ReadTimeASCII(char *string, BYTE format);
void ds1305_TimeToStr(struct ds1305_time *time, char *string, BYTE format);
void ds1305_WriteTime (struct ds1305_time *time);
void ds1305_ReadTime (struct ds1305_time *time);
BYTE _ReadYear (void);
void _WriteYear (BYTE year);
BYTE _ReadMonth (void);
void _WriteMonth (BYTE month);
BYTE _ReadDay (BYTE reg);
void _WriteDay (BYTE day, BYTE reg);
BYTE _ReadDate (void);
void _WriteDate (BYTE date);
BYTE _ReadHours (BYTE *format, char *am_pm, BYTE reg);
void _WriteHours (BYTE hours, BYTE format, BYTE am_pm, BYTE reg);
BYTE _ReadMinutes (BYTE reg);
void _WriteMinutes (BYTE minutes, BYTE reg);
BYTE _ReadSeconds(BYTE reg);
void _WriteSeconds (BYTE seconds, BYTE reg);
void ds1305_SPIInit(void);
void _EnableOSC(BYTE state);
void _WriteProtect(BYTE state);
BYTE ds1305_ReadStatusRegister(void);
BYTE _ReadStatusRegister (void);
BYTE _IsWriteProtect(void);
BYTE ds1305_ReadControlRegister(void);
BYTE _ReadControlRegister(void);
void _WriteControlRegister (BYTE temp);
void _ChipEnable(BYTE status);
void delay(uchar n);
*/
BYTE utils_DecToBcd(BYTE number)
{
BYTE temp;
temp = ((number / 10) << 4); /* extract the upper digit */
temp |= number % 10; /* extract the lower digit */
return temp;
}
BYTE utils_BcdToDec(BYTE number)
{
BYTE temp;
temp = ((number >> 4) * 10); /* upper digit */
temp += (number & 0x0f); /* lower digit */
return temp;
}
void delay(uchar n)
{
while (n--)
{
__asm
nop
nop
__endasm;
}
}
void spi_MasterInit(void) //初始化SPI
{
SPDAT=0;
SPSTAT=SPIF|WCOL;
SPCTL = SSIG|SPEN|MSTR|CPOL|CPHA|SPDLL;
}
void spi_SlaveSelect (BYTE action){
if (action == TRUE)
CS = 0x00;
else
CS = 0x01;
}
BYTE spi_MasterTransmit(BYTE dat)
{
SPDAT = dat; //trigger SPI send
while (!(SPSTAT & SPIF)); //wait send complete
SPSTAT = SPIF | WCOL; //clear SPI status
return SPDAT; //return received SPI data
}
void _ChipEnable(BYTE status)
{
if (status == TRUE)
spi_SlaveSelect(TRUE);
else
spi_SlaveSelect(FALSE);
}
void _WriteControlRegister (BYTE temp)
{
_ChipEnable(TRUE);
spi_MasterTransmit(ds1305_REG_CR + ds1305_REG_WRITE_OFFSET);
spi_MasterTransmit(temp);
_ChipEnable(FALSE);
}
BYTE _ReadControlRegister(void)
{
BYTE temp;
_ChipEnable(TRUE);
spi_MasterTransmit(ds1305_REG_CR); /* read the currents CR register */
temp = spi_MasterTransmit(0x00);
_ChipEnable(FALSE);
return (temp);
}
BYTE ds1305_ReadControlRegister(void)
{
return _ReadControlRegister();
}
BYTE _IsWriteProtect(void)
{
return (_ReadControlRegister() && (1 < ds1305_BIT_WP));
}
BYTE _ReadStatusRegister (void)
{
BYTE temp;
_ChipEnable(TRUE);
spi_MasterTransmit(ds1305_REG_SR);
temp = spi_MasterTransmit(0x00);
_ChipEnable(FALSE);
return (temp);
}
BYTE ds1305_ReadStatusRegister(void)
{
return _ReadStatusRegister();
}
void _WriteProtect(BYTE state)
{
BYTE temp;
temp = _ReadControlRegister(); /* make a backup */
if (state == TRUE)
temp |= (1 << ds1305_BIT_WP); /* WP enable, active high */
else
temp &= ~(1 << ds1305_BIT_WP); /* WP disable */
_WriteControlRegister(temp); /* write back the changed ds1305_BIT_WP bit */
}
void _EnableOSC(BYTE state)
{
BYTE temp;
temp = _ReadControlRegister();
if (state == TRUE)
temp &= ~(1 << ds1305_BIT_EOSC); /* EOSC enable, active low */
else
temp |= (1 << ds1305_BIT_EOSC); /* EOSC disable */
_WriteControlRegister(temp);
}
void ds1305_SPIInit(void)
{
spi_MasterInit ();
_WriteProtect(FALSE); /* must run before _EnableOSC() */
_EnableOSC(TRUE);
}
void _WriteSeconds (BYTE seconds, BYTE reg)
{
_ChipEnable(TRUE);
spi_MasterTransmit(reg);
spi_MasterTransmit(utils_DecToBcd(seconds));
_ChipEnable(FALSE);
}
BYTE _ReadSeconds(BYTE reg)
{
BYTE temp;
_ChipEnable(TRUE);
spi_MasterTransmit(reg);
temp = utils_BcdToDec(spi_MasterTransmit(0x00));
_ChipEnable(FALSE);
return temp;
}
void _WriteMinutes (BYTE minutes, BYTE reg)
{
_ChipEnable(TRUE);
spi_MasterTransmit(reg);
spi_MasterTransmit(utils_DecToBcd(minutes));
_ChipEnable(FALSE);
}
BYTE _ReadMinutes (BYTE reg)
{
BYTE temp;
_ChipEnable(TRUE);
spi_MasterTransmit(reg);
temp = utils_BcdToDec(spi_MasterTransmit(0x00));
_ChipEnable(FALSE);
return temp;
}
void _WriteHours (BYTE hours, BYTE format, BYTE am_pm, BYTE reg)
{
BYTE temp;
temp = utils_DecToBcd(hours);
if (format == ds1305_24H)
temp &= ~(1 << 6); /* 24 hours format */
else {
temp |= (1 << 6); /* 12 hours format */
if (am_pm == ds1305_AM)
temp &= ~(1 << 5); /* AM */
else
temp |= (1 <<5); /* PM */
};
_ChipEnable(TRUE);
spi_MasterTransmit(reg);
spi_MasterTransmit(temp);
_ChipEnable(FALSE);
}
BYTE _ReadHours (BYTE *format, char *am_pm, BYTE reg)
{
BYTE temp, temp2;
_ChipEnable(TRUE);
spi_MasterTransmit(reg);
temp = spi_MasterTransmit(0x00); /* dummy read */
_ChipEnable(FALSE);
temp2 = 0;
if (temp & (1 << 6)) { /* check 12h mode */
*format = !ds1305_24H;
if (temp & (1 << 5)) /* check PM */
*am_pm = !ds1305_AM;
else
*am_pm = ds1305_AM;
temp2 = ((temp & 0x10) >> 4) * 10; /* 10hours is bit 4 */
}
else { /* 24H mode */
*format = ds1305_24H;
temp2 = ((temp & 0x30) >> 4) * 10; /* 10hours is bits 5 & 4 */
};
temp2 += (temp & 0x0f); /* hours */
return temp2;
}
void _WriteDate (BYTE date)
{
_ChipEnable(TRUE);
spi_MasterTransmit(ds1305_REG_DATE + ds1305_REG_WRITE_OFFSET);
spi_MasterTransmit(utils_DecToBcd(date));
_ChipEnable(FALSE);
}
BYTE _ReadDate (void)
{
BYTE temp;
_ChipEnable(TRUE);
spi_MasterTransmit(ds1305_REG_DATE);
temp = utils_BcdToDec(spi_MasterTransmit(0x00)); /* dummy read */
_ChipEnable(FALSE);
return temp;
}
void _WriteDay (BYTE day, BYTE reg)
{
_ChipEnable(TRUE);
spi_MasterTransmit(reg);
spi_MasterTransmit(utils_DecToBcd(day));
_ChipEnable(FALSE);
}
BYTE _ReadDay (BYTE reg)
{
BYTE temp;
_ChipEnable(TRUE);
spi_MasterTransmit(reg);
temp = utils_BcdToDec(spi_MasterTransmit(0x00)); /* dummy read */
_ChipEnable(FALSE);
return temp;
}
void _WriteMonth (BYTE month)
{
_ChipEnable(TRUE);
spi_MasterTransmit(ds1305_REG_MONTH + ds1305_REG_WRITE_OFFSET);
spi_MasterTransmit(utils_DecToBcd(month));
_ChipEnable(FALSE);
}
BYTE _ReadMonth (void)
{
BYTE temp;
_ChipEnable(TRUE);
spi_MasterTransmit(ds1305_REG_MONTH);
temp = utils_BcdToDec(spi_MasterTransmit(0x00)); /* dummy read */
_ChipEnable(FALSE);
return temp;
}
void _WriteYear (BYTE year)
{
_ChipEnable(TRUE);
spi_MasterTransmit(ds1305_REG_YEAR + ds1305_REG_WRITE_OFFSET);
spi_MasterTransmit(utils_DecToBcd(year));
_ChipEnable(FALSE);
}
BYTE _ReadYear (void)
{
BYTE temp;
_ChipEnable(TRUE);
spi_MasterTransmit(ds1305_REG_YEAR);
temp = utils_BcdToDec(spi_MasterTransmit(0x00)); /* dummy read */
_ChipEnable(FALSE);
return temp;
}
void ds1305_ReadTime (struct ds1305_time *time)
{
time->year = _ReadYear();
time->month = _ReadMonth();
time->date = _ReadDate();
time->day = _ReadDay(ds1305_REG_DAY);
time->hours = _ReadHours(&time->format, &time->am_pm, ds1305_REG_HOURS);
time->minutes = _ReadMinutes(ds1305_REG_MINUTES);
time->seconds = _ReadSeconds(ds1305_REG_SECONDS);
}
void ds1305_WriteTime (struct ds1305_time *time)
{
BYTE wp;
wp = _IsWriteProtect();
_WriteProtect(FALSE);
_WriteYear(time->year);
_WriteMonth(time->month);
_WriteDate(time->date);
_WriteDay(time->day, ds1305_REG_DAY + ds1305_REG_WRITE_OFFSET);
_WriteHours(time->hours, time->format, time->am_pm, ds1305_REG_HOURS + ds1305_REG_WRITE_OFFSET);
_WriteMinutes(time->minutes, ds1305_REG_MINUTES + ds1305_REG_WRITE_OFFSET);
_WriteSeconds(time->seconds, ds1305_REG_SECONDS + ds1305_REG_WRITE_OFFSET);
_WriteProtect(wp);
}
void ds1305_TimeToStr(struct ds1305_time *time, char *string, BYTE format)
{
BYTE ctr;
ctr = 0; /* beginning of string */
if (format == ds1305_ASCII_TIME)
goto time_only;
if (format == ds1305_ASCII_ALARM)
goto alarm_only;
/* year */
string[ctr++] = '2'; /* 20xx (century) is built in */
string[ctr++] = '0';
string[ctr++] = (time->year / 10) + 0x30; /* convert 10year to an ASCII number */
string[ctr++] = (time->year % 10) + 0x30; /* convert year to an ASCII number */
string[ctr++] = '-'; /* separator */
/* month */
string[ctr++] = (time->month / 10) + 0x30; /* convert 10month to an ASCII number */
string[ctr++] = (time->month % 10) + 0x30; /* convert month to an ASCII number */
string[ctr++] = '-'; /* separator */
/* date */
string[ctr++] = (time->date / 10) + 0x30; /* convert 10date to an ASCII number */
string[ctr++] = (time->date % 10) + 0x30; /* convert date to an ASCII number */
string[ctr++] = ' '; /* separator */
if (format == ds1305_ASCII_DATE)
goto end;
alarm_only: /* add the day of the alarm */
string[ctr++] = (time->day + 0x30);
string[ctr++] = ',';
string[ctr++] = ' ';
time_only: /* from here, convert the time part */
/* hours */
string[ctr++] = (time->hours / 10) + 0x30; /* convert 10hours to an ASCII number */
string[ctr++] = (time->hours % 10) + 0x30; /* convert hours to an ASCII number */
string[ctr++] = ':'; /* separator */
/* minutes */
string[ctr++] = (time->minutes / 10) + 0x30; /* convert 10minutes to an ASCII number */
string[ctr++] = (time->minutes % 10) + 0x30; /* convert minutes to an ASCII number */
string[ctr++] = ':'; /* separator */
/* seconds */
string[ctr++] = (time->seconds / 10) + 0x30; /* convert 10seconds to an ASCII number */
string[ctr++] = (time->seconds % 10) + 0x30; /* convert seconds to an ASCII number */
/* am/pm */
if (time->format != ds1305_24H) { /* check if 12h mode */
string[ctr++] = 0x20; /* separator (space) */
if (time->am_pm != ds1305_AM) { /* check if AM or PM */
string[ctr++] = 'P';
string[ctr++] = 'M';
}
else {
string[ctr++] = 'A';
string[ctr++] = 'M';
}
}
end:
string[ctr] = '\0'; /* end the string */
}
void ds1305_ReadTimeASCII(char *string, BYTE format)
{
struct ds1305_time time;
ds1305_ReadTime(&time);
ds1305_TimeToStr(&time, string, format);
}
BYTE _AsciiValidate(char *string)
{
#define _ASCII_OK 0;
BYTE status;
BYTE ctr;
status = ds1305_ASCII_UNDEFINED;
for (ctr = 0; (string[ctr] != '\0') || (ctr = 254); ctr++ ); /* find the length of the string, max 255 characters */
if (ctr == 0)
status = ds1305_ASCII_EMPTY;
else
if (ctr < 19)
status = ds1305_ASCII_TOO_SHORT;
else
if (ctr > 19)
status = ds1305_ASCII_TOO_LONG;
while (ctr == 19) {
if ((string[0] != '2') || (string[1] != '0')) {
status = ds1305_ASCII_INVALID;
break; /* no point continuing */
};
ctr = 2; /* the first 2 characters (century) are not needed */
if (isdigit(string[ctr]) && isdigit(string[ctr+1])){
//nop();//convert to numeric
__asm
nop
__endasm;}
else {
status = ds1305_ASCII_INVALID;
break;
};
};
return status;
}
BYTE _strncpyx (char *dest, char *src, BYTE n, BYTE x)
{
BYTE ctr;
for (ctr = 0; ctr <= n; ctr++) {
dest[ctr] = src[ctr + x];
};
dest[ctr+1] = '\0'; /* terminate the string */
return 0;
}
BYTE ds1305_WriteTimeAscii(char *string)
{
BYTE status;
char temp[3];
struct ds1305_time time;
//status = _AsciiValidate(string);
status = 0;
if (!status) { /* if no error with the string, proceed */
_strncpyx(temp, string, 2, 2);
time.year = atoi(temp);
_strncpyx(temp, string, 2, 5);
time.month = atoi(temp);
_strncpyx(temp, string, 2, 8);
time.date = atoi(temp);
_strncpyx(temp, string, 2, 11);
time.hours = atoi(temp);
_strncpyx(temp, string, 2, 14);
time.minutes = atoi(temp);
_strncpyx(temp, string, 2, 17);
time.seconds = atoi(temp);
time.day = 1;
time.format = ds1305_24H;
};
ds1305_WriteTime(&time);
return status;
}
void main(void)
{
//uchar buf[4]={0xbb,0xb6,0xd3,0xad};
uchar now[7];
ds1305_SPIInit();
ds1305_WriteTimeAscii("2012-03-29 09:57:00");
ds1305_ReadTimeASCII(now,ds1305_ASCII_TIME);
lcd_init();
//printstr(0x01,0x02,buf,0x04);
printstr(0x01,0x01,now,0x07);
while (1)
{
//ds1305_ReadTimeASCII(now,ds1305_ASCII_TIME);
}
}
|
|