1227|0

2014

帖子

0

TA的资源

纯净的硅(中级)

楼主
 

msp430g2553的IIC通信 [复制链接]

因为一个特殊的原因,必须用msp430g2553实现IIC通信,硬件的没弄出来,想软件模拟一下,结果本来预计一晚上的任务,硬生生变成了一晚上加一早上。。。。这块单片机IIC通信的主要槽点在于,你一旦把SDA引脚切换成输入模式进行ACK检测就会直接断开整个时序,我不是很懂为什么,反正我把它去了就好了,下面是根据山外的SCCB底层库改编的msp430g2553的IIC通信代码.
/**IIC.c**/
#include "MSP430G2553.h"
#include "IIC.h"
 
#define IIC_OUT P2OUT
#define IIC_DIR P2DIR
#define IIC_SEL P2SEL
#define IIC_IN  P2IN
 
#define SCL_H()         IIC_OUT|=BIT0
#define SCL_L()         IIC_OUT&=~BIT0
#define SCL_DDR_OUT()   IIC_DIR|=BIT0
#define SCL_DDR_IN()    IIC_DIR&=~BIT0
 
#define SDA_H()         P1OUT|=BIT4
#define SDA_L()         P1OUT&=~BIT4
#define SDA_IN()        P1IN&BIT4
#define SDA_DDR_OUT()   P1DIR|=BIT4
#define SDA_DDR_IN()    P1DIR&=~BIT4
 
static void SCCB_delay(uint16 i);
 
/*!
 *  @brief      SCCB延迟函数
 *  @param      time    延时时间
 *  @since      v5.0
 */
static void SCCB_delay(volatile uint16 time)
{
    while(time)
    {
        time--;
    }
}
 
/*!
 *  @brief      SCCB管脚配置
 *  @since      v5.0
 */
void SCCB_GPIO_init(void)
{
    IIC_SEL&=~BIT0;
    P1SEL&=~BIT4;
    //P2REN |=(BIT0+BIT1);
    SCL_DDR_OUT();
    SDA_DDR_OUT();
}
 
/*!
 *  @brief      SCCB起始信号
 *  @since      v5.0
 */
static uint8 SCCB_Start(void)
{
    SDA_H();
    SCL_H();
    SCCB_DELAY();
 
    //SDA_DDR_IN();
    if(!SDA_IN())
    {
        //SDA_DDR_OUT();
        //return 0;   /* SDA线为低电平则总线忙,退出 */
    }
    SDA_DDR_OUT();
    SDA_L();
 
    SCCB_DELAY();
    SCL_L();
 
    if(SDA_IN())
    {
        SDA_DDR_OUT();
        return 0;   /* SDA线为高电平则总线出错,退出 */
    }
    //SDA_DDR_OUT();
    //SDA_L();
    //SCCB_delay();
    return 1;
}
 
/*!
 *  @brief      SCCB停止信号
 *  @since      v5.0
 */
static void SCCB_Stop(void)
{
    SCL_L();
    //SCCB_DELAY();
    SDA_L();
    SCCB_DELAY();
    SCL_H();
    SCCB_DELAY();
    SDA_H();
    SCCB_DELAY();
}
 
/*!
 *  @brief      SCCB应答信号
 *  @since      v5.0
 */
static void SCCB_Ack(void)
{
    SCL_L();
    SCCB_DELAY();
    SDA_L();
    SCCB_DELAY();
    SCL_H();
    SCCB_DELAY();
    SCL_L();
    SCCB_DELAY();
}
 
/*!
 *  @brief      SCCB无应答信号
 *  @since      v5.0
 */
static void SCCB_NoAck(void)
{
    SCL_L();
    SCCB_DELAY();
    SDA_H();
    SCCB_DELAY();
    SCL_H();
    SCCB_DELAY();
    SCL_L();
    SCCB_DELAY();
}
 
/*!
 *  @brief      SCCB 等待应答
 *  @return     应答结果(0表示无应答,1表示有应答)
 *  @since      v5.0
 */
static int SCCB_WaitAck(void)
{
    SCL_L();
    //SDA_H();
    //SDA_DDR_IN();
 
    SCCB_DELAY();
    SCL_H();
 
    SCCB_DELAY();
 
    if(SDA_IN())           //应答为高电平,异常,通信失败
    {
        SDA_DDR_OUT();
        SCL_L();
        return 0;
    }
    SDA_DDR_OUT();
    SCL_L();
    return 1;
}
 
/*!
 *  @brief      SCCB 发送的数据
 *  @param      SendByte    需要发送的数据
 *  @since      v5.0
 */
static void SCCB_SendByte(uint8 SendByte)
{
    uint8 i = 8;
    while(i--)
    {
 
        if(SendByte & 0x80)     //SDA 输出数据
        {
            SDA_H();
        }
        else
        {
            SDA_L();
        }
        SendByte <<= 1;
        SCCB_DELAY();
        SCL_H();                //SCL 拉高,采集信号
        SCCB_DELAY();
        SCL_L();                //SCL 时钟线拉低
        //SCCB_DELAY();
    }
    //SCL_L();
}
 
/*!
 *  @brief      接收SCCB总线的数据
 *  @return     接收到的数据
 *  @since      v5.0
 */
static int SCCB_ReceiveByte(void)
{
    uint8 i = 8;
    uint8 ReceiveByte = 0;
 
    //SDA_H();
    //SCCB_DELAY();
    SDA_DDR_IN();
 
    while(i--)
    {
        ReceiveByte <<= 1;
        SCL_L();
        SCCB_DELAY();
        SCL_H();
        SCCB_DELAY();
 
        if(SDA_IN())
        {
            ReceiveByte |= 0x01;
        }
        else
        {
            ReceiveByte |= 0x00;
        }
    }
    SDA_DDR_OUT();
    SCL_L();
    return ReceiveByte;
}
 
/*****************************************************************************************
* 函数名:SCCB_WriteByte
* 描述  :写一字节数据
* 输入  :- WriteAddress: 待写入地址    - SendByte: 待写入数据  - DeviceAddress: 器件类型
* 输出  :返回为:=1成功写入,=0失败
* 注意  :无
*****************************************************************************************/
static int SCCB_WriteByte_one( uint16 WriteAddress , uint8 SendByte );
 
 
int SCCB_WriteByte( uint16 WriteAddress , uint8 SendByte )            //考虑到用sccb的管脚模拟,比较容易失败,因此多试几次
{
    uint8 i = 0;
    while( 0 == SCCB_WriteByte_one ( WriteAddress, SendByte ) )
    {
        i++;
        if(i == 20)
        {
            return 0 ;
        }
    }
    return 1;
}
 
int SCCB_WriteByte_one( uint16 WriteAddress , uint8 SendByte )
{
    if(!SCCB_Start())
    {
        return 0;
    }
    SCCB_SendByte( DEV_ADR );                    /* 器件地址 */
    if( !SCCB_WaitAck() )
    {
        SCCB_Stop();
        return 0;
    }
    SCCB_SendByte((uint8)(WriteAddress & 0x00FF));   /* 设置低起始地址 */
    SCCB_WaitAck();
    SCCB_SendByte(SendByte);
    SCCB_WaitAck();
    SCCB_Stop();
    return 1;
}
 
 
 
 
/******************************************************************************************************************
 * 函数名:SCCB_ReadByte
 * 描述  :读取一串数据
 * 输入  :- pBuffer: 存放读出数据  - length: 待读出长度    - ReadAddress: 待读出地址        - DeviceAddress: 器件类型
 * 输出  :返回为:=1成功读入,=0失败
 * 注意  :无
 **********************************************************************************************************************/
static int SCCB_ReadByte_one(uint8 *pBuffer,   uint16 length,   uint8 ReadAddress);
 
int SCCB_ReadByte(uint8 *pBuffer,   uint16 length,   uint8 ReadAddress)
{
    uint8 i = 0;
    while( 0 == SCCB_ReadByte_one(pBuffer, length, ReadAddress) )
    {
        i++;
        if(i == 30)
        {
            return 0 ;
        }
    }
    return 1;
}
 
int SCCB_ReadByte_one(uint8 *pBuffer,   uint16 length,   uint8 ReadAddress)
{
    if(!SCCB_Start())
    {
        return 0;
    }
    SCCB_SendByte( DEV_ADR );         /* 器件地址 */
    if( !SCCB_WaitAck() )
    {
        //SCCB_Stop();
        //return 0;
    }
    SCCB_SendByte( ReadAddress );           /* 设置低起始地址 */
    SCCB_WaitAck();
    SCCB_Stop();
 
    if(!SCCB_Start())
    {
        //return 0;
    }
 
    SCCB_SendByte( DEV_ADR + 1 );               /* 器件地址 */
 
    if(!SCCB_WaitAck())
    {
        //SCCB_Stop();
        //return 0;
    }
    while(length)
    {
        *pBuffer = SCCB_ReceiveByte();
        if(length == 1)
        {
            SCCB_NoAck();
        }
        else
        {
            SCCB_Ack();
        }
        pBuffer++;
        length--;
    }
    SCCB_Stop();
    return 1;
}
/*
 * IIC.h
 *
 *  Created on: 2017年11月25日
 *      Author: Admin
 */
 
#ifndef IIC_H_
#define IIC_H_
 
#include "common.h"
 
#define CPU_F ((double)8000000)   //外部高频晶振8MHZ
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/1000000.0))
#define delay_ms(x) __delay_cycles((long)(CPU_F*(double)x/1000.0))
 
#define SCCB_DELAY()    delay_us(1)
 
#define DEV_ADR 0x90    //设备地址
 
extern void SCCB_GPIO_init(void);
extern int SCCB_WriteByte( uint16 WriteAddress , uint8 SendByte);
extern int SCCB_ReadByte(uint8 *pBuffer,   uint16 length,   uint8 ReadAddress);
 
#endif /* IIC_H_ */

在主函数里面初始化一下时钟再调用一下SCCB_GPIO_init();之后就可以用SCCB_ReadByte和SCCB_WriteByte进行单字节的IIC通信了
SCCB_WriteByte
SCCB_WriteByte

 

 
点赞 关注

回复
举报
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表