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

📄 smbus.c

📁 C8051F020 / 040 等等单片机内部SMBUS总线驱动程序源代码(原创) 使用Keil C51编译环境 程序中没有使用SMBUS中断方式,使用查询中断方式运行,这样程序结构简单,便于
💻 C
字号:
//SMBUS.C

//------------------------------------------------------//
// YnKing 原创,转载请注明出处
// http://www.21mcu.com/
// ynpsps@sina.com
//------------------------------------------------------//

#include <C8051F020.H>
#include "SMBUS.H"
#include "API/API.H"

SMBUS_ROM24_Device ROM24CXX;
//------------------------------------------------------//
//                    SMBUS INIT                        //
//------------------------------------------------------//
void SMBUS_INIT(void)
{
    SMB0CN = 0x44;              // 允许SMBus 在应答周期发送ACK
    // SMBUS总线速度 = SYSCLK/(256-SMB0CR)
    // SMB0CR = 256-(SYSCLK/SMBUS总线速度)
    SMB0CR = -(SYSCLK/200000);
    //SMB0CR = -80;             // SYSCLK = 8MHz , SMBus 时钟频率 = 100kHz.
    //EIE1 |= 2;                    // SMBus 中断允许
    
    // 初始化ROM24设备
    //--- 24C256 ---
    #if SMBUS_ROM24_Enable == 1
        SMBUS_ROM24_Device_Init(&ROM24CXX , 0 , 2 , 32); // 器件地址=0 ; 器件寻址宽度2字节 ; 器件写页面大小32字节
    #endif
}

//======================================================//
//                     ROM24 部 分                      //
//======================================================//
#if SMBUS_ROM24_Enable == 1
//-----------------------------------//
//        ROM24 设备初始化           //
//-----------------------------------//
void SMBUS_ROM24_Device_Init(SMBUS_ROM24_Device *device , unsigned char chip_addr , unsigned char addrwidth , unsigned char pagesize)
{
    device->IsOpen = 1;
    device->Chip_Addr = chip_addr; // 器件地址
    device->AddrWidth = addrwidth; // 器件内部地址宽度
    device->PageSize = pagesize;   // 器件写页面大小
}
//------------------------------------------------------//
//                    SMBUS 写字节                      //
//------------------------------------------------------//
void SMBUS_ROM24_WBS(SMBUS_ROM24_Device *device , unsigned int byte_address , char *dout , unsigned char len)
// 注释 : 本子程序不使用中断,在程序中查询中断标志
// 参数 :
//      chip_addr : 器件地址 = 0 ~ 7
//      byte_address : 器件内部地址
//      dout : 写入器件中的数据
{
    unsigned char pageout;
    if(device->IsOpen != 1)return;
SMBUS_ROM24_WBS_ReSTART:
    AA = 1;
    // 总线开始
    STA = 1;
    while(!SI);
    // 写器件地址
    if(SMB0STA != SMB_START) goto SMBUS_ROM24_WBS_Err;
    SMB0DAT = 0xa0|(device->Chip_Addr<<1);
    STA = 0;
    SI = 0;
    
    while(!SI);
    if(SMB0STA != SMB_MTADDACK)
    {
        STO = 1;
        SI = 0;
        goto SMBUS_ROM24_WBS_ReSTART;
    }
    if(device->AddrWidth == 2)
    {
        // 写高位地址
        SMB0DAT = ((unsigned char*)(&byte_address))[0];
        SI = 0;
    	
        while(!SI);
        if(SMB0STA != SMB_MTDBACK) goto SMBUS_ROM24_WBS_Err;
    }
    
    // 写低位地址
    SMB0DAT = ((unsigned char*)(&byte_address))[1]; // 写
    SI = 0;
    
    pageout = byte_address&(device->PageSize-1);
    for(;len!=0;len--)
    {
        while(!SI);
        if(SMB0STA != SMB_MTDBACK) goto SMBUS_ROM24_WBS_Err;
        if(pageout >= device->PageSize)
        { // 越界,需要重新开始
SMBUS_ROM24_WBS_Re:
            STO = 1;
            STA = 1;
            SI = 0;
    		
            while(!SI);
            if(SMB0STA != SMB_START) goto SMBUS_ROM24_WBS_Err;
            SMB0DAT = 0xa0|(device->Chip_Addr<<1);
            STA = 0;
            SI = 0;
    		
            while(!SI);
            if(SMB0STA != SMB_MTADDACK) goto SMBUS_ROM24_WBS_Re;
            if(device->AddrWidth == 2)
    		{
                // 写高位地址
                SMB0DAT = ((unsigned char*)(&byte_address))[0];
            	SI = 0;
    	
                while(!SI);
                if(SMB0STA != SMB_MTDBACK) goto SMBUS_ROM24_WBS_Err;
    		}
    
            // 写低位地址
            SMB0DAT = ((unsigned char*)(&byte_address))[1]; // 写
            SI = 0;
    		
            while(!SI);
            if(SMB0STA != SMB_MTDBACK) goto SMBUS_ROM24_WBS_Err;
            pageout = 0;
    	}
    	
        // 写数据
        SMB0DAT = *dout;
        dout++;
        SI = 0;
        pageout++;
        byte_address++;
    }
    
    while(!SI);
    // 完成
SMBUS_ROM24_WBS_Err:
    STO = 1;
    SI = 0;
}

//------------------------------------------------------//
//                    SMBUS 读字节                      //
//------------------------------------------------------//
void SMBUS_ROM24_RBS(SMBUS_ROM24_Device *device , unsigned int byte_address , char *din , unsigned char len)
// 注释 : 本子程序不使用中断,在程序中查询中断标志
// 参数 :
//      device : 设备信息
//      byte_address : 器件内部地址
//      din : 读出器件中的数据
{
    if(device->IsOpen != 1)return;
SMBUS_ROM24_RBS_ReSTART:
    AA = 1;
    // 总线开始
    STA = 1;
    while(!SI);
    // 写器件地址
    if(SMB0STA != SMB_START) goto SMBUS_ROM24_RBS_Err;
    SMB0DAT = 0xa0|(device->Chip_Addr<<1);
    STA = 0;
    SI = 0;
    
    while(!SI);
    if(SMB0STA != SMB_MTADDACK)
    {
        STO = 1;
        SI = 0;
        goto SMBUS_ROM24_RBS_ReSTART;
    }
    if(device->AddrWidth == 2)
    {
        // 写高位地址
        SMB0DAT = ((unsigned char*)(&byte_address))[0];
        SI = 0;
    	
        while(!SI);
        if(SMB0STA != SMB_MTDBACK) goto SMBUS_ROM24_RBS_Err;
    }
    
    // 写低位地址
    SMB0DAT = ((unsigned char*)(&byte_address))[1]; // 写
    SI = 0;
    
    while(!SI);
    if(SMB0STA != SMB_MTDBACK) goto SMBUS_ROM24_RBS_Err;
    // 重新开始
    STA = 1;
    SI = 0;
    
    while(!SI);
    if(SMB0STA != SMB_RP_START) goto SMBUS_ROM24_RBS_Err;
    STA = 0;
    // 发送读器件命令
    SMB0DAT = 0xa1|(device->Chip_Addr<<1);
    SI = 0;
    
    while(!SI);
    if(SMB0STA != SMB_MRADDACK) goto SMBUS_ROM24_RBS_Err;
    //AA = 0;
    SI = 0;
    
    for(;len!=0;len--)
    {
        while(!SI);
        if(SMB0STA != SMB_MRDBACK) goto SMBUS_ROM24_RBS_Err;
        // 读数据
        *din = SMB0DAT;
        din++;
        if(len==1)
        { // 最后一个字节不发送ACK
            AA = 0;
    	}
        SI = 0;
    }
    while(!SI);
    // 完成
SMBUS_ROM24_RBS_Err:
    STO = 1;
    SI = 0;
}
#endif

//----------------------------------//
//       RFID HY502 设备驱动        //
//----------------------------------//
#if HY502_Enable == 1

bit SMBUS_WaitSI(unsigned char s)
{
    unsigned char c;
    for(c=10;c!=0;c++)
    {
        if(SI==1)
    	{
            if(SMB0STA == s)
                return 1;
        	else
            	break;
    	}
        delay_ms(1);
    }
    STO = 1;
    SI = 0;
    delay_ms(5);
    return 0;
}
//----------------//
//    读数据包    //
//----------------//
bit HY502_RP(unsigned char *p)
{
    bit r=0;
    unsigned char c,cCheckSum;
    c=0;
HY502_RP_ReSTART:
    AA = 1;
    // 总线开始
    STA = 1;
    if(!SMBUS_WaitSI(SMB_START)) goto HY502_RP_ReSTART;
    // 发送读命令
    SMB0DAT = 0xa1|(HY502_Addr<<1);
    STA = 0;
    SI = 0;
    
    if(!SMBUS_WaitSI(SMB_MRADDACK))
    {
        c++;
        if(c>=100)
            goto HY502_RP_Err;
        else
            goto HY502_RP_ReSTART;
    }
    SI = 0;
    
    p[0] = 2;
    cCheckSum = 0;
    for(c=0;c<p[0];c++)
    {
        if(!SMBUS_WaitSI(SMB_MRDBACK)) goto HY502_RP_Err;
        //while(!SI);
        //if(SMB0STA != SMB_MRDBACK) goto HY502_RP_Err;
        // 读数据
        p[c] = SMB0DAT;
        cCheckSum += p[c];
        if(c >= p[0])
        { // 最后一个字节不发送ACK
            AA = 0;
    	}
        SI = 0;
    }
    while(!SI);
    //if(cCheckSum)goto HY502_RP_Err;
    r=1;
HY502_RP_Err:
    STO = 1;
    SI = 0;
    return r;
}

//----------------//
//    写数据包    //
//----------------//
bit HY502_WP(unsigned char *p)
{
    bit r=0;
    unsigned char c,cCheckSum;
    c=0;
HY502_WP_ReSTART:
    AA = 1;
    // 总线开始
    STA = 1;
    
    if(!SMBUS_WaitSI(SMB_START))
    {
        c++;
        if(c>=100)
            goto HY502_WP_Err;
        else
            goto HY502_WP_ReSTART;
    }
    //while(!SI);
    // 发送读命令
    //if(SMB0STA != SMB_START) goto HY502_WP_ReSTART;
    SMB0DAT = 0xa0|(HY502_Addr<<1);
    STA = 0;
    SI = 0;
    
    if(!SMBUS_WaitSI(SMB_MTADDACK)) goto HY502_WP_ReSTART;
    /*while(!SI);
    if(SMB0STA != SMB_MTADDACK)
    {
        STO = 1;
        SI = 0;
        goto HY502_WP_ReSTART;
    }*/
    
    cCheckSum = 0;
    for(c=0;c<p[0];c++)
    {
        SMB0DAT = p[c];
        SI = 0;
    	
        cCheckSum ^= p[c];
        if(!SMBUS_WaitSI(SMB_MTDBACK)) goto HY502_WP_Err;
        //while(!SI);
        //if(SMB0STA != SMB_MTDBACK) goto HY502_WP_Err;
    }
    
    // 最后发送校验和
    SMB0DAT = cCheckSum;
    SI = 0;
    if(!SMBUS_WaitSI(SMB_MTDBACK)) goto HY502_WP_Err;
    //while(!SI);
    //if(SMB0STA != SMB_MTDBACK) goto HY502_WP_Err;
    r = 1;
HY502_WP_Err:
    STO = 1;
    SI = 0;
    return r;
}

//------------------------//
//      读 卡 类 型       //
//------------------------//
code unsigned char RCardTypeCmd[] = {0x02,0x19};
unsigned int HY502_RCardType(void)
{
    unsigned char t[5];
    if(!HY502_WP(RCardTypeCmd))return 0;
    if(!HY502_RP(t))return 0;
    return *((unsigned int*)(&t[2]));
}

//------------------------//
//      读 卡 ID 号       //
//------------------------//
code unsigned char RCardIDCmd[] = {0x02,0x20};
unsigned long HY502_RCardID(void)
{
    unsigned char t[7];
    if(!HY502_WP(RCardIDCmd))return 0;
    if(!HY502_RP(t))return 0;
    return *((unsigned long*)(&t[2]));
}

//------------------------//
//       卡 休 眠         //
//------------------------//
code unsigned char CardIdleCmd[] = {0x02,0x12};
bit HY502_CardIdle(void)
{
    unsigned char t[3];
    if(!HY502_WP(CardIdleCmd))return 0;
    if(!HY502_RP(t))return 0;
}


#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -