📄 twi_master_drv._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 + -