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

📄 twi_master_drv._c

📁 at90can128底层驱动 有SPI,TWI,总线,CAN接口等
💻 _C
字号:
/*头文件*/
#include "twi_master_drv.h"

/*全局变量定义*/
uchar	twi_busy;	//=FALSE,TWI通讯空闲;=TRUE,TWI通讯忙
uchar	twi_err;	//TWI通讯状态
uchar	twi_nb_transmited;	//收发字节数
//uchar	twi_recptr;

TWI_MSG	twi_message;	//TWI数据结构

/*****************************************************************************
函数介绍:TWI初始化,设置通讯波特率和启动通讯
输入参数:
输出参数:
返回值:无
*****************************************************************************/
void twi_lib_init(void)
{
  //Twi_set_baudrate(0xf9);		//8MOSC 1K
  //Twi_set_status(0x02);
  //Twi_set_baudrate(0x62);		//8MOSC 10K
  //Twi_set_status(0x01);
  Twi_set_baudrate(0x20);		//8MOSC 100K
  Twi_set_status(0x00);

  //Twi_set_address(0x51);
  Twi_init_hw(TWI_CONFIG);
}

/*****************************************************************************
函数介绍:在从机或主机模式下,TWI信息的收发的主流程状态。
此函数在TWI通讯事件发生时,对各个状态进行解码,查询和中断方式都可以。
输入参数:
输出参数:
返回值:无
*****************************************************************************/
void twi_decode_status()
{
switch ( Twi_get_status()&0xF8 ) // switch (SSTA)
    {
    //  STATE 00h: Bus Error has occurred
    //  ACTION:    Enter not addressed SLV mode and release bus
    case  0x00 :
    twi_busy = FALSE;
    twi_err  = TWI_BUS_ERROR;
    break;


    //STATE 08h: A start condition has been sent
    //ACTION:    SLR+R/W are transmitted, ACK bit received
    case 0x08 :
    Twi_clear_start();    //Pas besoin fait en hard ???
    Twi_set_data(twi_message.address<<1);
    if ( twi_message.rw == TWI_READ )
    {
		  Twi_set_data(Twi_get_data()+1); // Add 1 for Read bit in AdrWord    modify by zmq
    }
    Twi_set_aa(); //from here to 0x18 transmit or 0x40 receive
    break;

    //STATE 10h: A repeated start condition has been sent
    //ACTION:    SLR+R/W are transmitted, ACK bit received
    case 0x10 :
    Twi_clear_start();          // Reset STA bit in SSCON
    Twi_set_data(twi_message.address<<1);
    if ( twi_message.rw == TWI_READ )
    {
			Twi_set_data(Twi_get_data()+1); // Add 1 for Read bit in AdrWord    modify by zmq
    }
    Twi_set_aa();               // wait on ACK bit
    break;

    //STATE 18h:   SLR+W was transmitted, ACK bit received
    //ACTION:      Transmit data byte, ACK bit received
    //PREVIOUS STATE: 0x08 or 0x10
    case 0x18 :                 // master transmit, after sending
    twi_nb_transmited=0;        // slave address, now load data
    Twi_set_data(*(twi_message.buf)); // byte and send it

    if (twi_message.nbbytes==0) // no datas to transmit
        {
        Twi_set_stop();
        twi_err  = TWI_TRANSFER_OK;
        twi_busy = FALSE;       // transfer complete, clear twi_busy
        }
    Twi_clear_si();
    break;

    //STATE 20h:   SLR+W was transmitted, NOT ACK bit received
    //ACTION:      Transmit STOP
    case 0x20 :
    Twi_set_stop(); // Twi_set_stop will also clear twiint flag
    twi_busy = FALSE;
    twi_err  = TWI_HOST_ADR_NACK;
    break;

    //STATE 28h:   DATA was transmitted, ACK bit received
    //ACTION:      If last byte, send STOP, else send more data bytes
    case 0x28:                  // master transmit, after sending ; data byte, ACK received
    twi_nb_transmited++;        // inc nb data transmit on message
    twi_message.buf++;          // inc pointer ti data to be transmited
    if ( twi_nb_transmited < twi_message.nbbytes  ) // if there are still bytes to send
        {
        Twi_set_data(*(twi_message.buf));
        Twi_set_aa();           // wait on ACK bit
        }
    else
        {                    //run out of data, send stop,
        Twi_set_stop(); // Twi_set_stop will also clear twiint flag
        twi_err  = TWI_TRANSFER_OK;
        twi_busy = FALSE;         //transfer complete, clear twi_busy
        }
    break;

    //STATE 30h:   DATA was transmitted, NOT ACK bit received
    //ACTION:      Transmit STOP
    case 0x30 :
    Twi_set_stop();     // Twi_set_stop will also clear twiint flag
    twi_busy = FALSE;
    twi_err  = TWI_HOST_ADR_NACK;
    break;

    //STATE 38h:   Arbitration lost in SLA+W or DATA.
    //ACTION:      Release bus, enter not addressed SLV mode
    //             Wait for bus lines to be free
    case 0x38 :
    twi_busy = FALSE;
    twi_err  = TWI_ARBITRATION_LOST;
    Twi_clear_si();
    // #ifdef USER_TWI_FCT_ARBITRATION_LOST_IN_SLA+W_OR_DATA
    // TWI_fct_arb_lostinSLAorDATA();
    // #endif
    break;

   //MASTER RECEIVER MODE FOLLOWS
   //STATE 40h:   SLA+R transmitted, ACK received
   //ACTION:      Receive DATA, ACK to be returned
   //PREVIOS STATE: 0x08 or 0x10
    case 0x40 :               //master receive, after sending
         if ( twi_message.nbbytes == 1 )
         {
            Twi_clear_aa(); // only one data to receive, noACK to be send after the fisrt incoming data
            Twi_clear_si();
         }
    else if (!twi_message.nbbytes      ) Twi_set_stop(); // special case: no data to read ! clear also twint
    else
        {
        Twi_set_aa();      //wait on ACK bit
        twi_nb_transmited=0;      //data byte to be received, NOT ACK bit to follow  --> 0x58
        }
    break;

    //STATE 48h:   SLA+R transmitted, NOT ACK received
    //ACTION:      Transmit STOP
    case 0x48 :
    Twi_set_stop(); //clear also twint
    twi_busy = FALSE;
    twi_err  = TWI_HOST_ADR_NACK;
    break;

    //STATE 50h:   Data has been received, ACK returned
    //ACTION:      Read DATA. If expecting more continue else STOP
    case 0x50 : //master receive, received data
                //byte and ACK, copy it into
    *(twi_message.buf+twi_nb_transmited) = Twi_get_data();      //buffer
    twi_nb_transmited++;
    if ( twi_nb_transmited < (twi_message.nbbytes-1) ) Twi_set_aa(); // get more bytes
    else
    {
      Twi_clear_aa();           //only one more byte to come
      Twi_clear_si();
    }
    break;

    //STATE 58h:   Data has been received, NOT ACK returned
    //ACTION:      Read DATA. Generate STOP
    case 0x58 :
    *(twi_message.buf+twi_nb_transmited) = Twi_get_data();
    Twi_set_stop();
    twi_busy = FALSE;
    twi_err  = TWI_RECEIVE_OK;
    break;

    //if we arrived here, unknown state has occurred.....
    default :
    Twi_set_stop();
    twi_busy = FALSE;
    twi_err  = TWI_UNKNOWN;
    break;
    }
}

/*****************************************************************************
函数介绍:TWI主机模式,查询方式
输入参数:	slave_addr:从机地址
			rw:=TWI_WRITE发送模式;=TWI_READ接收模式
			nbbytes:最大字节数
			*info:数据缓存地址
输出参数:
返回值:twi_err:TWI通讯状态
 - TWI_TRANSFER_OK		发送完成
 - TWI_RECEIVE_OK		接收完成
 - TWI_BUS_ERROR		总线冲突
 - TWI_HOST_ADR_NACK	从机地址无应答
 - TWI_HOST_DATA_NACK	从机数据无应答(不存在)
 - TWI_ARBITRATION_LOST	仲裁失败
 - TWI_UNKNOWN			TWI状态错误	
 - TWI_NOT_FREE			TWI通信忙
 - TWI_OK				TWI通信开始
*****************************************************************************/
unsigned char twi_send_message_polling( uchar slave_addr,uchar rw, uchar nbbytes, uchar *info )
{
  twi_message.address = slave_addr;
  twi_message.rw = rw;
  twi_message.nbbytes = nbbytes;
  twi_message.buf = info;
  Twi_wait_hw_stop();
  Disable_twi_interrupt(); //FIXME
  twi_nb_transmited=0;
  if (!twi_busy)
  {
    twi_busy =1;
    twi_err = TWI_OK;
    Twi_set_start();
    while (twi_busy)
        {
        Twi_wait_event();
        twi_decode_status();
//        Twi_clear_si(); //REMOVE FROM MAIN LOOP, ADDED IN ALL NECESARY CASE (See JSB /RLE)
        }
   // Twi_set_stop(); RLE
    return twi_err;
  }
  Twi_set_stop();
  return TWI_NOT_FREE;
}

/*****************************************************************************
函数介绍:TWI主机模式,中断方式
输入参数:	slave_addr:从机地址
			rw:=TWI_WRITE发送模式;=TWI_READ接收模式
			nbbytes:最大字节数
			*info:数据缓存地址
输出参数:
返回值:twi_err:TWI通讯状态
 - TWI_TRANSFER_OK		发送完成
 - TWI_RECEIVE_OK		接收完成
 - TWI_BUS_ERROR		总线冲突
 - TWI_HOST_ADR_NACK	从机地址无应答
 - TWI_HOST_DATA_NACK	从机数据无应答(不存在)
 - TWI_ARBITRATION_LOST	仲裁失败
 - TWI_UNKNOWN			TWI状态错误	
 - TWI_NOT_FREE			TWI通信忙
 - TWI_OK				TWI通信开始
*****************************************************************************/
unsigned char twi_send_message_interrupt( uchar slave_addr,uchar rw, uchar nbbytes, uchar *info)
{
  twi_message.address = slave_addr;
  twi_message.rw = rw;
  twi_message.nbbytes = nbbytes;
  twi_message.buf = info;
  Twi_wait_hw_stop();
  twi_nb_transmited=0;
  if (!twi_busy)
  {
    twi_err = TWI_OK;
    twi_busy =1;
    Enable_twi_interrupt();
    Twi_set_start();
    return twi_err;
  }
  Twi_set_stop();
  return TWI_NOT_FREE;
}

/*****************************************************************************
函数介绍:TWI中断例程
输入参数:
输出参数:
返回值:无
*****************************************************************************/
//#pragma vector = TWI_vect
//__interrupt void twi_interrupt()
#pragma interrupt_handler twi_interrupt:36
void twi_interrupt()
{
  twi_decode_status();
//  Twi_clear_si(); //REMOVE FROM MAIN LOOP, ADDED IN ALL NECESARY CASE (See JSB /RLE)
}

/*****************************************************************************
函数介绍:主机发送模式
输入参数:	slave_addr:从机地址
			nbbytes:最大字节数
			*info:数据缓存地址
输出参数:
返回值:无
*****************************************************************************/
void TWI_MW(uchar slave_addr,uchar nbbytes,uchar *info)    //用户程序
{
	//twi_send_message_polling(slave_addr, TWI_WRITE, nbbytes, info);	//查询方式
	twi_send_message_interrupt(slave_addr, TWI_WRITE, nbbytes, info);	//中断方式
}

/*****************************************************************************
函数介绍:主机接收模式
输入参数:	slave_addr:从机地址
			nbbytes:最大字节数
			*info:数据缓存地址
输出参数:
返回值:无
*****************************************************************************/
void TWI_MR(uchar slave_addr,uchar nbbytes,uchar *info)
{
	//twi_send_message_polling(slave_addr, TWI_READ, nbbytes, info);	//查询方式
	twi_send_message_interrupt(slave_addr, TWI_READ, nbbytes, info);	//中断方式
}

uchar receive_ok(void)
{
 	  if(twi_err == TWI_RECEIVE_OK)
	  	  return TRUE;
	  else
	  	  return FALSE;
}

void main(void)
{
int i;
	
	uchar Mdisbuf[3]={0x90,0x55,0x55};
	uchar Mkeybuf[4];
	
	twi_busy = 0;
	
	CLI();
	twi_lib_init();
	SEI();
	

/*while(1)	
	if(!twi_busy)
		TWI_MR(0x4F, 2, Mkeybuf);  //向从机温度传感器0x4F读取2个数据	
*/
while(1)
{	
	if(!twi_busy)	
		TWI_MR(0x21, 4, Mkeybuf);
	
	if(!twi_busy){
		Mdisbuf[2]=0x09;//点亮			
		TWI_MW(0x21, 3, Mdisbuf); //向从机0x21写入3个数据
	}
	for(i=0;i<2000;i++);
	if(!twi_busy){
		Mdisbuf[2]=0x89;//灭			
		TWI_MW(0x21, 3, Mdisbuf); //向从机0x21写入3个数据
	}
	for(i=0;i<2000;i++);
}
/*
while(1)	
	if(!twi_busy)
		TWI_MR(0x21, 4, Mkeybuf); 	//向从机0x21读取4个数据,中断方式
*/
	while(1);	
}


	
	

⌨️ 快捷键说明

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