⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msp430_i2c.c

📁 通用的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 + -