📄 msp430_i2c.c
字号:
//==================================//
//通用MSP430—I2C程序
//===================================//
#include "sk2000.h"
//P3.2 SCL
//P3.3 SDA
//
#define IIC_SCL BIT5 //SCL定义P9.5
#define IIC_SDA BIT4 //SDA定义P9.4
#define SDA_1 P9OUT |= BIT4 //SDA = 1
#define SDA_0 P9OUT &=~ BIT4 //SDA = 0
#define SCL_1 P9OUT |= BIT5 //SCL = 1
#define SCL_0 P9OUT &=~ BIT5 //SCL = 0
#define DIR_IN P9DIR &=~ BIT4; //I/O口为输入
#define DIR_OUT P9DIR |= BIT4 //I/0口为输出
#define DIR_OUTss P9DIR |= (BIT4+BIT5) //I/0口为输出
#define SDA_IN (P9IN & BIT4) //Read SDA
#define ACK 0
#define NOACK 1
#define FALSE 0
#define TRUE 1
#define RUN 1
#define IIC_WRITE 0xa0
#define IIC_READ 0xa1
#define REG_READ 0Xd1 //register read
#define REG_WRITE 0Xd0 //register write
#define WRITEPROTECT 0x0b
#define YEAR 0x08
#define MOUNTH 0x07
#define DAY 0x06
#define DATE 0x05
#define HOUR 0x04
#define MINUTE 0x03
#define SECOND 0x02
#define CONTROL 0x01
#define FLAGS 0x00
#define WDTFLAG 0x09
#define WDTTIME 0x0a
uchar Time[7];
uchar counter = 0;
unsigned int a[10];
unsigned int b[10];
unsigned int c[10];
unsigned int d[10];
unsigned int ReadData[6]={0};
uchar TEMP_Page = 0;
//======================================
/*
;* Description: define the struct value to save time
*/
//======================================
struct str_time//时间结构变量
{
uchar year;
uchar month;
uchar date;
uchar day;
uchar hour;
uchar minute;
uchar secend;
}time;
//struct str_time time={0x08,0x12,0x31,0x01,0x23,0x59,0x54};//十六进制
struct str_time time={8,12,31,1,23,59,54}; //十进制
//======================================
//struct str_time time;
/*
;* Name: hex_to_bcd
;* Description: 十六进制数转换成BDC码格式
;* Calls: None
;* Input: 需要转换的十六进制数
;* Outputs: 转换后的BCD码
*/
//======================================
uchar hex_to_bcd(uchar condata)
{
uchar temp;
uchar temp0;
uchar temp10;
temp10=condata/10;
temp0=condata%10;
temp=(temp10<<4)|temp0;
return(temp);
}
//======================================
/*
;* Name: bcd_to_hex
;* Description: BCD码格式转换成十六进制数
;* Calls: None
;* Input: 需要转换的BCD码
;* Outputs: 转换后的十六进制数
*/
//======================================
uchar bcd_to_hex(uchar condata)
{
uchar temp;
uchar temp0;
uchar temp10;
temp10=(condata&0xF0)>>4;
temp0=condata&0x0F;
temp=temp10*10+temp0;
return(temp);
}
//=================================================
//
//=================================================
static void Delay(unsigned int n)
{
unsigned int i;
for (i=0; i<n;i++);
}
void Start(void)
{
DIR_OUT;
SDA_1;
Delay(2);
SCL_1;
Delay(2);
SDA_0;
Delay(2);
SCL_0;
Delay(2);
}
void Stop(void)
{
SCL_0;
Delay(2);
DIR_OUT;
Delay(2);
SDA_0;
Delay(2);
SCL_1;
Delay(2);
SDA_1;
}
void SendAck(unsigned char flag)
{
DIR_OUT;
Delay(2);
if(flag == 0)
{
SDA_0;
}
else
{
SDA_1;
}
Delay(2);
SCL_1;
Delay(2);
SCL_0;
Delay(2);
}
void Init(void)
{
DIR_OUTss;
Delay(2);
SCL_0;
Delay(2);
SDA_0;
Delay(2);
SCL_1;
Delay(2);
SDA_1;
}
uchar WriteByte(unsigned char WriteData)
{
uchar i,n=255;
DIR_OUT;
for (i=0; i<8; i++)
{
if((WriteData & 0x80) == 0x80)
{
SDA_1;
}
else
{
SDA_0;
}
Delay(1);
SCL_1;
Delay(1);
WriteData <<= 1;
SCL_0;
Delay(1);
}
DIR_IN; //注意位置
SCL_1;
Delay(2);
DIR_IN; //放在SCL_1后面是有问题的
while (SDA_IN /*sda==1*/ /*调试方便,可以不要*/)
{
if(!(--n))
{
SCL_0;
return(FALSE);
}
}
//DIR_OUT;
SCL_0;
Delay(2);
return(TRUE);
}
uchar ReadByte(void)
{
uchar i,TempData = 0;
DIR_IN;
Delay(2);
for (i=0; i<8; i++)
{
SCL_1;
TempData=TempData << 1;//或TempData <<= 1;不能用TempData << 1;
Delay(1);
if (SDA_IN/*sda==1*/)
{
TempData |= 0x1;
}
Delay(1);
SCL_0;
Delay(1);
}
return(TempData);
}
uchar ReceiveAck()
{
uchar i = 255;
DIR_IN; //注意位置
SCL_1;
Delay(2);
DIR_IN; //放在SCL_1后面是有问题的
while (SDA_IN /*sda==1*/ /*调试方便,可以不要*/)
{
if(!(--i))
{
SCL_0;
return(FALSE);
}
}
//DIR_OUT;
SCL_0;
Delay(2);
return(TRUE);
}
void Acknowledge(void)
{
//SCL_0;
Delay(2);
DIR_OUT;
SDA_0;
SCL_1;
Delay(2);
SCL_0;
}
unsigned int ReadWord(unsigned char unit/*address*/)
{
unsigned char HighData = 0;
unsigned char LowData = 0;
unsigned int TempData = 0;
Start();
WriteByte(0xa0);
WriteByte(unit);
Start();
WriteByte(0xa1);
LowData = ReadByte();
Acknowledge();
HighData = ReadByte();
Stop();
TempData = (HighData << 8) + LowData;
Delay(1000);
return(TempData);
}
//==================================================
//
//==================================================
void ReadWords(uint16_t Page,uint16_t unit,uint16_t *buffer,uint16_t n)
{
uint16_t high;
//TEMP_Page=(uchar)(Page<<2);
//TEMP_Page=(Page<<2);
Start();
WriteByte(0xa0);
WriteByte(Page); //不能去掉,为什么???其实是Page和unit合起来总的地址
//TEMP_Page=(uchar)(Page<<2);
WriteByte(unit);
Start();
WriteByte(0xa1);
while(n--)
{
high=ReadByte();
SendAck(ACK);
*buffer = ReadByte();
SendAck(ACK);
*buffer |= (high<<8);
b[n]=*buffer;
buffer++;
}
high= ReadByte();
SendAck(ACK);
*buffer = ReadByte();
SendAck(NOACK);
*buffer |= (high<<8);
Stop();
Delay(10);
}
void WriteWord(unsigned char unit/*address*/, unsigned int WriteData)
{
unsigned char LowData = 0;
unsigned char HighData = 0;
LowData = (unsigned char)WriteData;
HighData = (unsigned char)(WriteData >> 8);
Start();
WriteByte(0xa0);
WriteByte(unit);
WriteByte(LowData);
WriteByte(HighData);
Stop();
Delay(2000);
}
void WriteWords(uint16_t Page,uint16_t unit/*address*/, uint16_t *buffer,uint16_t n)
{
uint16_t i;
Start();
WriteByte(0xa0);
WriteByte(Page);
WriteByte(unit);
for(i=0;i<n;i++)
{
WriteByte((*buffer)>>8);
WriteByte(*buffer);
a[i]=*buffer;
buffer++;
}
Stop();
Delay(10);
}
//=====================================
void WriteReg(uchar RegAdd,uchar Wdata)
{
Start();
WriteByte(REG_WRITE);
RegAdd = RegAdd & 0x1f;
WriteByte(RegAdd);
WriteByte(Wdata);
Stop();
}
//=====================================
uchar ReadReg(uchar RegAdd)
{
uchar RetValue;
Start();
WriteByte(REG_WRITE);
WriteByte(RegAdd);
Start();
WriteByte(REG_READ);
RetValue = ReadByte();
SCL_1; SDA_1;SCL_0;
Stop();
return RetValue;
}
//======================================
/*
;* Name: time_control
;* Description: 控制时钟走停
;* Calls: None
;* Input: 输入控制标记
;* Outputs: None
*/
//======================================
void time_control(uchar type)
{
if(type==RUN)
WriteReg(CONTROL,0X00);
else
WriteReg(CONTROL,0X80);
}
//============================================
/*
;* Name: read_time
;* Description: 读取FM3808内部时钟值并转换成十六进制值
;* Calls: None
;* Input: None
;* Outputs: None
*/
//============================================
void read_time(void)
{
uchar temp[7];
uchar i,flagstempa,flagstempb;
flagstempa=ReadReg(FLAGS);
flagstempb=(flagstempa|0x01)&0xFD;
//=========================
WriteReg(FLAGS,flagstempb);
Start();
WriteByte(REG_WRITE);
WriteByte(SECOND);
Start();
WriteByte(REG_READ);
for(i=0;i<6;i++)
{
temp[i]=ReadByte();
SendAck(ACK);
}
temp[6]=ReadByte();
SendAck(NOACK);
Stop();
WriteReg(FLAGS,flagstempb&0XFE);
//==========================
time.year=bcd_to_hex(temp[6]);
time.month=bcd_to_hex(temp[5]);
time.date=bcd_to_hex(temp[4]);
time.day=bcd_to_hex(temp[3]);
time.hour=bcd_to_hex(temp[2]);
time.minute=bcd_to_hex(temp[1]);
time.secend=bcd_to_hex(temp[0]);
}
//======================================
/*
;* Name: write_time
;* Description: 设置FM3808时钟寄存器
;* Calls: None
;* Input: None
;* Outputs: None
*/
//======================================
void write_time(void)
{
uchar temp[7];
uchar i,flagstempa,flagstempb;
flagstempa=ReadReg(FLAGS);
flagstempb=(flagstempa|0x02)&0xFE;
WriteReg(FLAGS,flagstempb);
temp[6]=hex_to_bcd(time.year);
temp[5]=hex_to_bcd(time.month);
temp[4]=hex_to_bcd(time.date);
temp[3]=hex_to_bcd(time.day);
temp[2]=hex_to_bcd(time.hour);
temp[1]=hex_to_bcd(time.minute);
temp[0]=hex_to_bcd(time.secend);
Start();
WriteByte(REG_WRITE);
WriteByte(SECOND);
for(i=0;i<7;i++)
{
WriteByte(temp[i]);
}
Stop();
}
//======================================
void Init_timerA(void)
{
TACCTL0 = CCIE; // TACCR0中断使能
TACCR0 = 2000;
TACTL = TASSEL_2 + MC_2; // TA时钟 SMCLK, 连续模式
}
//=======================================
/*
void SendData(uchar Sdata)
{
SBUF = Sdata;
while(!TI);
TI = 0;
}
*/
//=======================================
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop Watchdog
FLL_CTL0 |= DCOPLUS + XCAP18PF; // Set load capacitance for xtal
SCFI0 |= FN_2; // x2 DCO, 4MHz nominal DCO
SCFQCTL = 36; // (36+1) x 2 x 32768 = 2.424832Mhz
Init_timerA();
Init();
WriteReg(CONTROL,0x80); //停止时钟
//uint Add;
//uint16_t tab[]={0x0606,0x0707,0x0808,0x0908,0x0a09,0x0100};
//uchar ReadData=0;
//SendData(0x11);
//WriteReg(WRITEPROTECT,0x08); //软件写保护1/4
//WriteReg(WRITEPROTECT,0x10); //软件写保护1/2
//WriteReg(WRITEPROTECT,0x18); //软件写保护全部
WriteReg(CONTROL,0x00); //启动时钟
WriteReg(FLAGS,0x00); //清除标志位
/*
WriteReg(FLAGS,0x02); //允许写操作
WriteReg(YEAR,0x08); //写时间
WriteReg(MOUNTH,0x01);
WriteReg(DAY,0x30);
WriteReg(DATE,0x03);
WriteReg(HOUR,0x15);
WriteReg(MINUTE,0x15);
WriteReg(SECOND,0x00);
WriteReg(FLAGS,0x00); //停止写操作
*/
/*
WriteReg(FLAGS,0x06); //允许写操作
WriteReg(YEAR,0x08); //写时间
WriteReg(MOUNTH,0x12);
WriteReg(DAY,0x31);
WriteReg(DATE,0x01);
WriteReg(HOUR,0x23);
WriteReg(MINUTE,0x59);
WriteReg(SECOND,0x54);
WriteReg(FLAGS,0x04); //停止写操作
*/
write_time();
//WriteReg(FLAGS,0x01); //允许读操作
_EINT();
while(1)
{
}
}
//=========================================
//定时中断,读取时钟
//=========================================
#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A0 (void)
{
/***读写FM3130最好在主程序里进行,采用基本定时器定时操作***
***或者置标记,当在主程序里进行存储,但时钟可定时响应 ***/
TACCR0 += 24238; //10ms
if(counter <= 10)
{
uint16_t tab[]={0x1111,0x1111,0x1111,0x1111,0x1111,0x1111};
WriteWords(255,0,tab,6);
ReadWords(255,0,ReadData,6);
read_time();
counter++;
}
if(10<counter < 40)
{
uint16_t tab[]={0x0606,0x0707,0x0808,0x0908,0x0a09,0x0100};
WriteWords(255,0,tab,6);
ReadWords(255,0,ReadData,6);
read_time();
counter++;
}
if(counter == 255)
{
counter = 0 ;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -