微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 51单片机—再论IIC—软件通用包(汇编、c语言)—03

51单片机—再论IIC—软件通用包(汇编、c语言)—03

时间:11-25 来源:互联网 点击:

非应答函数、应答检测函数(这里书上把它看作了数据传送的那部分,管他呢~~~呵呵),还有发送一字节数据,接受以字节数据,发送n字节数据,接收n字节数据这几个子程序。

1)发送一字节数据WR_BYTE

该子程序是向虚拟的IIC总显得数据线SDA上发送一字节数据的操作。调用该子程序前,将要发送的数据送入A中。

还是先汇编,然后c代码:

;-----------------------------------------------------------------
;发送字节子程序
;字节数据放入ACC
;每发送一个字节筪掉用一次CACK(检测应答子程序),取应答位
WR_BYTE:
MOVR0,#08H;8位数据长度送R0
W_LP:
RLCA;发送数据左移,使发送位入c
JCW_R1;判读发送1,还是发送0,发送1,转入W_R1
SJMPW_R0;发送0转入W_R0
W_LP1:
DJNZR0,W_LP
NOP
RET
W_R1: ;发送1
SETBSDA
NOP
SETBSCL
NOP
NOP
NOP
NOP
NOP
CLRSCL
SJMPW_LP1
W_R0: ;发送0
CLRSDA
NOP
SETBSCL
NOP
NOP
NOP
NOP
NOP
CLRSCL
SJMPW_LP1

//----------------------------------------------------------------------
//写一个字节函数
void send_byte(uchar c)
{
uchar bit_cnt;
for(bit_cnt=0;bit_cnt<8;bit_cnt++)//循环传送8位
{
if((c //取当前发送位
sda=1;
else
sda=0;
_nop_();
scl=1;//发送到数据线上
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
scl=0;
}
}

2)接收一字节数据RD_BYTE(这个的汇编感觉并不肯定,有可能有错~~,当然c语言还是没问题的,呵呵)

;----------------------------------------------------------------------
;读取字节子程序
;读出的值再ACC中
;每取一个字节要发送一个应达或者非应答信号(要知道你读取就成了从机,就要发送一个信号告诉主机)
RD_BYTE:
MOVR0,#08H;8位数据长度
R_LP:
SETBSDA;置SDA为输入方式
NOP
CLRSCL;置时钟线为低电平,准备接收数据
NOP
NOP
NOP
NOP
NOP
SETBSCL
NOP
MOVC,SDA;读取数据位
RLCA;进行数据位的处理
NOP
DJNZR0,R_LP;没有到8位,再来一次
RET

//------------------------------------------------------------------------
//接收一个字节函数
//返回接收的8位数据
uchar rec_byte()
{
uchar temp;
uchar bit_cnt;
temp=0;
sda=1; //置数据线为输入方式
for(bit_cnt=0;bit_cnt<8;bit_cnt++)
{
_nop_();
scl=0; //置时钟线为低电平,准备接收数据
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
scl=1;
_nop_();
_nop_();
temp<=1;
if(sda==1)//接收当前数据位,接收内容放入temp中
temp+=1;
_nop_();
_nop_();
}
scl=0;
_nop_();
_nop_();
return(temp);
}

3)向被控器件发送n个字节数据子程序MCU_WRN_BYTE

;-----------------------------------------------------------------------
;向器件指定地址写入N个数据
;入口参数:器件从地质SLA,器件子地址SUBA、发送数据缓冲区MTD、发送字节数NUMBYTE
;占用:A,R0,R1,R3,CY
MCU_WRN_BYTE:
MOVA,NUM_BYTE
MOVR3,A
LCALLSTART;启动总线
MOVA,SLA
LCALLWR_BYTE;发送器件地址
LCALLCACK
JNBACK,RET_WRN
MOVA,SUBA;指定子地址,并发送
LCALLWR_BYTE
LCALLCACK
MOVR1,#MTD
WRN_DA:
MOVA,@R1
LCALLWR_BYTE;开始写入数据
LCALLCACK
JNBACK,MCU_WRN_BYTE
INCR1
DJNZR3,WRN_DA;判断写完没有
RET_WRN:
LCALLSTOP
RET

//---------------------------------------------------------------
//向器件指定地址按页写函数(这里虽然是说按页,其实原理是一样的~~,要是不明白可以看上一篇我整理的)
//入口参数有4个:器件地址码、器件单元地址、写入的数据串的指针、写入的字节个数
//写入成功,返回1;不成功,返回0,使用后必须结束总线
bit mcu_send_string(uchar add,uchar rom_add,uchar *s,uchar num)
{
uchar i;
IIC_start();
send_byte(add);//发送器件地址码
IIC_ack_acc();
if(ack==0)
return(0);//有应答,发送ROM的单元地址
send_byte(rom_add);
IIC_ack_acc();
if(ack==0)
return(0);
for(i=0;i //连续发送num个字节数据
{
send_byte(*s);
IIC_ack_acc();
if(ack==0)
return(0);
s++;
}
IIC_stop();
return(1);
}

4)从被控器件读取n个字节数据子程序MCU_RDN_BYTE

;--------------------------------------------------------------------------------
;从器件地址读取N个数据
;入口参数:器件从地址,器件子地址SUBA,接收字节数NUM_BYTE
;出口参数:接收数据缓冲区
;占用:A,R0,R1,R2,R3,CY
MCU_RDN_BYTE:
MOVR3,NUM_BYTE
LCALLSTART
MOVA,SLA
LCALLWR_BYTE;发送器件地址
LCALLCACK
JNBACK,RET_RDN
MOVA,SUBA;指定子地址
LCALLWR_BYTE
LCALLCACK
LCALLSTART
MOVA,SLA
INCA;准备进行读操作
LCALLWR_BYTE
LCALLCACK
JNBACK,MCU_RDN_BYTE
MOVR1,#MRD
RDN1:
LCALLRD_BYTE;读操作开始
MOV@R1,A
DJNZR3,SACK
LCALLMNACK;最后一个字节发非应答位
RET_RDN:
LCALLSTOP
RET
SACK:
LCALLMACK;发送应答位
INCR1
SJMPRDN1

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top