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

📄 smbus_master_f33x.c

📁 一些C8051f330的C程序
💻 C
字号:
//-----------------------------------------------------------------------------
//
// 文件名:SMBus_Master_F33x.c
//
// 编写人:JS
//
// 编写时间:2004/1/3
//
// 目标器件: C8051F33x
//
// 编译工具: Silicon Laboratories IDE
//
//-----------------------------------------------------------------------------
//程序描述:
//   C8051F330作为主器件,C8051F310作为从器件,定时器1为I2C时钟源,定时器3为SCL低电平超时检测,
//此程序为单字节收发.收发数据可以由用户自己定义。

//-----------------------------------------------------------------------------
//头文件包含
//-----------------------------------------------------------------------------
#include <c8051f330.h>

//-----------------------------------------------------------------------------
//常量定义
//-----------------------------------------------------------------------------
#define  SYSCLK         24500000             // 系统工作频率
#define  SMB_FREQUENCY  50000                // SCL时钟 
#define  WRITE          0x00                 // SMBus 写命令
#define  READ           0x01                 // SMBus 读命令

//-----------------------------------------------------------------------------
// 设备地址 (高7位)
//-----------------------------------------------------------------------------
#define  F310_SLAVE     0xf0                 //  从机设备地址

//-----------------------------------------------------------------------------
// 状态向量(只有高4位)
//-----------------------------------------------------------------------------
#define  SMB_MTSTA      0xE0                 // 准备发送
#define  SMB_MTDB       0xC0                 // 发送数据字节
#define  SMB_MRDB       0x80                 // 接收数据字节
//-----------------------------------------------------------------------------------
//全局变量定义
//----------------------------------------------------------------------------------
unsigned char SMB_DATA_IN;                   // 接收缓冲字节                                         
unsigned char SMB_DATA_OUT;                  // 发送缓冲字节
unsigned char TARGET;                        // 从机地址
bit SMB_BUSY;                                // 读写忙标志位
bit SMB_RW;                                  // 读写标志位
sbit LED = P1^3;                             // LED在P3.3口

//-----------------------------------------------------------------------------
//定时器3特殊功能寄存器定义
//-----------------------------------------------------------------------------

sfr16    TMR3RL   = 0x92;                   
sfr16    TMR3     = 0x94;                  

//------------------------------------------------------------------------------------
// 函数定义
//------------------------------------------------------------------------------------

void SMBus_Init (void);
void Timer1_Init (void);
void Timer3_Init (void);
void Port_Init (void);
void SMBus_ISR (void);
void Timer3_ISR (void);
void SMB_Write (void);
void SMB_Read (void);

//------------------------------------------------------------------------------------
// 主程序
//------------------------------------------------------------------------------------

void main (void)
{
unsigned char i, error;                 
   PCA0MD &= ~0x40;                          // 禁止看门狗

   OSCICN |= 0x03;                           // 使用内部振荡器(24500000)
                                            
   Port_Init ();                             // 内部交叉开关及I/O初始化

   Timer1_Init ();                           // 定时器1初始化,作为SMBus的时钟源
                                         
   Timer3_Init ();                           // 定时器3初始化,作为SMBus SCL信号低电平
                                             // 超时检测

   SMBus_Init ();                            // 初始化并使能SMBus

   EIE1 |= 1;                                // SMBus 中断使能
   IE |= 0x20;                               // 定时器2中断使能
   EA = 1;                                   // 总中断使能

//------------------------初始化结束----------------------------------------

   i = 0;                                    // 数据发送计数
   error = 0;                                // 通讯失败计数
   LED = 0;                                  // 关闭LED
   while (1)
   {
    for (i=0;i<255;i++)
        {      
         SMB_DATA_OUT = i;                   // 定义要发送的数据
         TARGET = F310_SLAVE;                // 从机地址
                                        
         SMB_Write();                      

    
         TARGET = F310_SLAVE;              
		                              
          SMB_Write();
         if(SMB_DATA_IN != SMB_DATA_OUT)    
            error++;                        
            LED = (!LED);                    // LED 状态取反       
	  }
     }
                     
   }
//------------------------------------------------------------------------------------
// SMBus发送程序
//------------------------------------------------------------------------------------

void SMB_Write (void)
{
   while (SMB_BUSY);            
   SMB_BUSY = 1;               
   SMB_RW = 0;                      
   STA = 1;                               
}

//------------------------------------------------------------------------------------
// SMBus接收程序
//------------------------------------------------------------------------------------

void SMB_Read (void)
{
   while (SMB_BUSY);         
   SMB_BUSY = 1;                  
   SMB_RW = 1;                     
   STA = 1;                           
   while (SMB_BUSY);                   
}

//------------------------------------------------------------------------------------
// SMBus初始化
//------------------------------------------------------------------------------------

void SMBus_Init (void)
{
   SMB0CF = 0x5D;                                                                                                   
   SMB0CF |= 0x80;                          
}

//------------------------------------------------------------------------------------
// 定时器3初始化程序
//------------------------------------------------------------------------------------

void Timer3_Init (void)
{
   TMR3CN = 0x00;                            //  定时器3工作在16位自动重装入方式

   TMR3 = -(SYSCLK/12/40);                   // 定时器3配制为25ms溢出
   TMR3RL = -(SYSCLK/12/40);               
   CKCON &= ~0x40;                           // 定时器3时钟源=SYSCLK/12
   TMR3 |= 0x04;                             //  使能定时器3
}

//------------------------------------------------------------------------------------
// 定时器1初始化
//------------------------------------------------------------------------------------

void Timer1_Init (void)
{
   CKCON &= ~0x0B;                           // 定时器1时钟源 = SYSCLK / 12
   TMOD = 0x20;                              // 定时器1工作在8位自动重装入方式
   TH1 = -(SYSCLK/SMB_FREQUENCY/12/3);                                            
   TL1 = -(SYSCLK/SMB_FREQUENCY/12/3);                                           
   TR1 = 1;                                  // 定时器1使能
}

//-----------------------------------------------------------------------------------
// I/O口初始化
//-----------------------------------------------------------------------------------
void Port_Init (void)
{
   XBR0 = 0x04;                              //  SMBus 分配到P0.0、P0.1
   XBR1 = 0x40;                    
   P0MDIN = 0xFF;                         
   P0MDOUT = 0x00;                      
   P1MDOUT = 0xff; 
}

//------------------------------------------------------------------------------------
// SMBus中断服务程序
//------------------------------------------------------------------------------------

void SMBus_ISR (void) interrupt 7
{
   bit FAIL;                                 // 通讯失败标志位
                                            
   bit ADDR_SEND;                            // 发送从机地址标志位
                                             

   switch (SMB0CN & 0xF0)                    //  状态向量
   {
                                     
     case SMB_MTSTA:                     
          SMB0DAT = TARGET;              
         SMB0DAT |= SMB_RW;                  // 装入从机地址和读写位  
		 
		 STA = 0;                            // 清发送位
         ADDR_SEND = 1;                      //此时发送的是从机地址和读写位,置标志位为1
         break;
//----------------------------------------------------------------------------
                                         // 主机发送:数据发送
      case SMB_MTDB:
         if (ACK)                            // 从机应答信号?
         {
            if (ADDR_SEND)                   // 前一次发送的是否是从机地址
            {                            
               ADDR_SEND = 0;                //  如是从机地址,下一次将不再发送从机地址
               if (SMB_RW==WRITE)            // 前一次发送的命令是读还是写
               {
                  SMB0DAT = SMB_DATA_OUT;    // 前一次发送的命令如果是写,就装入要发送的数据
               }
               else {}                       // 如果这个命令是读, 程序将不会写SMB0DAT
                                             // (切换到接收模式)
            }
            else                             // 前一次发送的不是从机地址
            {                             
               STO = 1;                      // 置停止位为1
               SMB_BUSY = 0;                 // 设置SMBus总线空闲
            }
         }
         else                                // 如果接收到的是非应答信号,
         {
            FAIL = 1;                        // 就设置失败标志位,并退出中断
                                             
         }
         break;

      // 主机接收:单字节接收
      case SMB_MRDB:
         SMB_DATA_IN = SMB0DAT;              // 保存接收字节
         SMB_BUSY = 0;                       // 设置SMBus总线空闲
         ACK = 0;                            // 发送应答信号
                                             

         STO = 1;                            // 发送停止位
         break;

      default:
         FAIL = 1;                         
         break;
   }

   if (FAIL)                                 // 是否有通讯失败,
   {
      SMB0CN &= ~0x40;                       // 复位总线
      SMB0CN |= 0x40;
      SMB_BUSY = 0;                          // SMBus 总线空闲
   }

   SI=0;                                     // 清SMBus中断为标志位
}

//-----------------------------------------------------------------------------------
// 定时器3中断服务程序 
//-----------------------------------------------------------------------------------
//
//定时器3中断表示SMBus总线的SCL位号低电平超时 
// 这里将禁止和重新使能SMBus总线
//
void Timer3_ISR (void) interrupt 14
{
   SMB0CN &= ~0x40;                          // 禁止SMBus
   SMB0CN |= 0x40;                           // 重新使能SMBus
   TMR3CN &= ~0x80;                          // 清定时器3中断标志位 
}

⌨️ 快捷键说明

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