msp430单片机有多少条内核指令(用MSP430的IO模拟I2C协议读写EEPROM)
msp430单片机有多少条内核指令(用MSP430的IO模拟I2C协议读写EEPROM)以下为实现IO模拟I2C协议的源程序/************************************************************************************************** MCU型号: MSP430F6736A 编译平台: IAR for MSP430 6.40.1 实验项目: IO模拟I2C协议 **************************************************************************************************/ #include "msp430.h" #include "msp430f6736a.h" #include "stdio.h"
I2C接口是单片机开发中很常用的一种接口,比如一些EEPROM,ADC,DAC等器件都通过I2C接口对芯片进行控制,或读写里面的数据。
I2C协议比较简单,容易实现,可以通过MCU的IO口来模拟实现,避免操作芯片里面的I2C控制器。
本文以MSP430为例,写了一个完整的IO模拟I2C的代码。当使用其他类型的MCU时,也可以轻松的将其移植过去。
原理图
以下为实现IO模拟I2C协议的源程序
/**************************************************************************************************
MCU型号: MSP430F6736A
编译平台: IAR for MSP430 6.40.1
实验项目: IO模拟I2C协议
**************************************************************************************************/
#include "msp430.h"
#include "msp430f6736a.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "math.h"
#define uchar unsigned char
#define uint unsigned int
//---------------------------------
// 初始化MCU
//---------------------------------
void Mcu_Init(void)
{
//---------------------------------
// 初始化系统时钟
//---------------------------------
WDTCTL = WDTPW WDTHOLD; // 禁止看门狗
__bic_SR_register(GIE); // 禁止所有中断
// 初始化XT1 并使其正常工作
UCSCTL6 &= ~(XT1OFF XT1BYPASS XTS);
UCSCTL6 |= XT1DRIVE_3;
UCSCTL6 |= XCAP_3;
do
{
UCSCTL7 &= ~XT1LFOFFG;
} while (UCSCTL7 & XT1LFOFFG);
// XT1CLK作为DCO输入
UCSCTL3 = SELREF__XT1CLK FLLREFDIV__1;
// 禁止 FLL 控制
__bis_SR_register(SCG0);
// DCO=31 MOD=0
UCSCTL0 = 0x1f00;
// DCO 范围: 23.7MHz - 54.1MHz
UCSCTL1 = DCORSEL_5;
// fDCO分频系数D = 2 N = 374
// fDCOCLK = D * (N 1) * FLLRef = 2 * (374 1) * 32768 = 24576000 Hz
UCSCTL2 = FLLD__2 | 374;
// 允许 FLL 控制
__bic_SR_register(SCG0);
__delay_cycles(384000);
do
{
UCSCTL7 &= ~(DCOFFG);
} while (UCSCTL7 & DCOFFG);
// ACLK=XT1CLK SMCLK=DCOCLK MCLK=DCOCLK
UCSCTL4 = SELA__XT1CLK SELS__DCOCLK SELM__DCOCLK;
//----------------------------------------------------------
// P2功能【外接信号】 功能 方向 初始值
// P2.1 | PM_UCB0SIMO | PM_UCB0SDA | COM7 |【I2C_SDA】 0[I/O] 1[O] [1]
// P2.0 | PM_UCB0SOMI | PM_UCB0SCL | COM6 |【I2C_SCL】 0[I/O] 1[O] [1]
//----------------------------------------------------------
P2SEL = 0;
P2DIR = 0xff;
P2OUT = 0xff;
P2REN |= 0x02;
}
//---------------------------------
// I2C协议
//---------------------------------
#define SETB_I2C_SCL (P2OUT|=BIT0)
#define CLR_I2C_SCL (P2OUT&=~bit0)
#define SETB_I2C_SDA (P2OUT|=BIT1)
#define CLR_I2C_SDA (P2OUT&=~BIT1)
#define I2C_SDA_IS_SET (P2IN&BIT1)
#define I2C_SDA_IS_CLR ((P2IN&BIT1)==0)
#define I2C_SDA_INPUT (P2DIR&=~BIT1)
#define I2C_SDA_OUTPUT (P2DIR|=BIT1)
uchar I2C_Byte;
void Start_I2C(void)
{
SETB_I2C_SDA;
SETB_I2C_SCL;
CLR_I2C_SDA;
CLR_I2C_SCL;
}
void Stop_I2C(void)
{
CLR_I2C_SDA;
SETB_I2C_SCL;
SETB_I2C_SDA;
}
void Send_ACK(void)
{
CLR_I2C_SDA;
SETB_I2C_SCL;
CLR_I2C_SCL;
}
void Send_NACK(void)
{
SETB_I2C_SDA;
SETB_I2C_SCL;
CLR_I2C_SCL;
}
void To_I2C(void)
{
uchar i bitset;
bitset = 0x80;
for (i=0; i<8; i )
{
if (bitset & I2C_Byte) SETB_I2C_SDA;
else CLR_I2C_SDA;
bitset /= 2;
SETB_I2C_SCL;
CLR_I2C_SCL;
}
// 将I2C_SDA切换到输入模式
I2C_SDA_INPUT;
Send_NACK();
// 将I2C_SDA切换到输出模式
I2C_SDA_OUTPUT;
}
void From_I2C(void)
{
uchar i bitset;
// 将I2C_SDA切换到输入模式
I2C_SDA_INPUT;
SETB_I2C_SDA;
bitset = 0x80;
I2C_Byte = 0x00;
for (i=0; i<8; i )
{
SETB_I2C_SCL;
if (I2C_SDA_IS_SET) I2C_Byte |= bitset;
CLR_I2C_SCL;
bitset /= 2;
}
// 将I2C_SDA切换到输出模式
I2C_SDA_OUTPUT;
}
//---------------------------------
// 写EEPROM(24CL04)
//---------------------------------
void WriteEE(uint EEAddr uchar *RamAddr uint Len)
{
uint i;
if (Len == 0) return;
Start_I2C();
I2C_Byte = (uchar)((EEAddr & 0xff00) >> 7);
I2C_Byte &= 0x02;
I2C_Byte = 0xa0;
To_I2C();
I2C_Byte = (uchar)(EEAddr & 0x00ff);
To_I2C();
for (i=0; i<Len; i )
{
I2C_Byte = RamAddr[i];
To_I2C();
}
Stop_I2C();
}
//---------------------------------
// 读EEPROM(24CL04)
//---------------------------------
void ReadEE(uint EEAddr uchar *RamAddr uint Len)
{
uint i;
if (Len == 0) return;
Start_I2C();
I2C_Byte = (uchar)((EEAddr & 0xff00) >> 7);
I2C_Byte &= 0x02;
I2C_Byte = 0xa0;
To_I2C();
I2C_Byte = (uchar)(EEAddr & 0x00ff);
To_I2C();
Start_I2C();
I2C_Byte = (uchar)((EEAddr & 0xff00) >> 7);
I2C_Byte &= 0x02;
I2C_Byte = 0xa1;
To_I2C();
for (i=0; i<Len; i )
{
From_I2C();
RamAddr[i] = I2C_Byte;
if (i != (Len-1))
{
Send_ACK();
}
}
Send_NACK();
Stop_I2C();
}
//---------------------------------
// 主流程
//---------------------------------
void main(void)
{
uchar i ctmp sbuf[10];
// 初始化MCU
Mcu_Init();
// 初始化LCD
Lcd_Init();
Disp_RomString(Msg_WriteEE LINE1 NORMAL);
Disp_RomString(Msg_ReadEE LINE4 NORMAL);
i = 0;
while(1)
{
ctmp = i;
WriteEE(0 &ctmp 1);
sprintf((char *)sbuf "d" ctmp);
Disp_RamString8x16(sbuf LINE1 11 NORMAL);
DELAY_400ms;
ctmp = 0;
ReadEE(0 &ctmp 1);
sprintf((char *)sbuf "d" ctmp);
Disp_RamString8x16(sbuf LINE4 11 NORMAL);
DELAY_400ms;
i ;
}
}
视频演示内容:先向EEPROM的地址0写入一个字节,然后从此地址读出,看是否与写入的内容一致