Ⅰ 【求助】STC12C5A60S系列单片机,实现AD采样并用数码管显示,利用AD采样得到的值控制输出占空比可调的PWM
#include<reg52.h>
#include <I2C.H>
#define PCF8591 0x90 //PCF8591 地址
//else IO
sbit LS138A=P2^2;
sbit LS138B=P2^3;
sbit LS138C=P2^4;
//此表为 LED 的字模, 共阴数码管 0-9 -
unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
unsigned char AD_CHANNEL;
unsigned long xdata LedOut[8];
unsigned int D[32];
/*******************************************************************
DAC 变换, 转化函数
*******************************************************************/
bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val)
{
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(c); //发送控制字节
if(ack==0)return(0);
SendByte(Val); //发送DAC的数值
if(ack==0)return(0);
Stop_I2c(); //结束总线
return(1);
}
/*******************************************************************
ADC发送字节[命令]数据函数
*******************************************************************/
bit ISendByte(unsigned char sla,unsigned char c)
{
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(c); //发送数据
if(ack==0)return(0);
Stop_I2c(); //结束总线
return(1);
}
/*******************************************************************
ADC读字节数据函数
*******************************************************************/
unsigned char IRcvByte(unsigned char sla)
{ unsigned char c;
Start_I2c(); //启动总线
SendByte(sla+1); //发送器件地址
if(ack==0)return(0);
c=RcvByte(); //读取数据0
Ack_I2c(1); //发送非就答位
Stop_I2c(); //结束总线
return(c);
}
//******************************************************************/
main()
{ char i,j;
while(1)
{/********以下AD-DA处理*************/
switch(AD_CHANNEL)
{
case 0: ISendByte(PCF8591,0x41);
D[0]=IRcvByte(PCF8591)*2; //ADC0 模数转换1 放大2倍显示
break;
case 1: ISendByte(PCF8591,0x42);
D[1]=IRcvByte(PCF8591)*2; //ADC1 模数转换2
break;
case 2: ISendByte(PCF8591,0x43);
D[2]=IRcvByte(PCF8591)*2; //ADC2模数转换3
break;
case 3: ISendByte(PCF8591,0x40);
D[3]=IRcvByte(PCF8591)*2; //ADC3 模数转换4
break;
case 4: DACconversion(PCF8591,0x40, D[4]/4); //DAC 数模转换
break;
}
// D[4]=400; //数字--->>模拟输出
D[4]=D[0]; // 把模拟输入 采样的信号 通过数模转换输出
if(++AD_CHANNEL>4) AD_CHANNEL=0;
/********以下将AD的值送到LED数码管显示*************/
LedOut[0]=Disp_Tab[D[1]%10000/1000];
LedOut[1]=Disp_Tab[D[1]%1000/100];
LedOut[2]=Disp_Tab[D[1]%100/10]|0x80;
LedOut[3]=Disp_Tab[D[1]%10];
LedOut[4]=Disp_Tab[D[0]%10000/1000];
LedOut[5]=Disp_Tab[D[0]%1000/100];
LedOut[6]=Disp_Tab[D[0]%100/10]|0x80;
LedOut[7]=Disp_Tab[D[0]%10];
for( i=0; i<8; i++)
{P0 = LedOut[i];
switch(i) //使用switch 语句控制138译码器 也可以是用查表的方式 学员可以试着自己修改
{
case 0:LS138A=0; LS138B=0; LS138C=0; break;
case 1:LS138A=1; LS138B=0; LS138C=0; break;
case 2:LS138A=0; LS138B=1; LS138C=0; break;
case 3:LS138A=1; LS138B=1; LS138C=0; break;
case 4:LS138A=0; LS138B=0; LS138C=1; break;
case 5:LS138A=1; LS138B=0; LS138C=1; break;
case 6:LS138A=0; LS138B=1; LS138C=1; break;
case 7:LS138A=1; LS138B=1; LS138C=1; break;
}
for (j = 0 ; j<90 ;j++) { ;} //扫描间隔时间
}
P0 = 0;
}
}
Ⅱ 基于STC89C52单片机的电子时钟系统的设计
就弄个AT24C02读写程序,注释详细看这个也应该用不到专门的时钟芯片,思路:开机进入主循环之前读取芯片中的数据,设置个标志位没30秒取反一次。或者但秒=0或为60时取反一次也是半分种吸和或断开,利用单片机本身的定时器,例如每个50ms中断一次20次就是一秒,bit ack; //应答标志位sbit SDA=P2^1;
sbit SCL=P2^0;/*------------------------------------------------
启动总线
------------------------------------------------*/
void Start_I2c()
{
SDA=1; //发送起始条件的数据信号
_Nop();
SCL=1;
_Nop(); //起始条件建立时间大于4.7us,延时
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; //发送起始信号
_Nop(); //起始条件锁定时间大于4μ
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; //钳住I2C总线,准备发送或接收数据
_Nop();
_Nop();
}
/*------------------------------------------------
结束总线
------------------------------------------------*/
void Stop_I2c()
{
SDA=0; //发送结束条件的数据信号
_Nop(); //发送结束条件的时钟信号
SCL=1; //结束条件建立时间大于4μ
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1; //发送I2C总线结束信号
_Nop();
_Nop();
_Nop();
_Nop();
}
/*----------------------------------------------------------------
字节数据传送函数
函数原型: void SendByte(unsigned char c);
功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0 假)
发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
------------------------------------------------------------------*/
void SendByte(unsigned char c)
{
unsigned char BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) //要传送的数据长度为8位
{
if((c<<BitCnt)&0x80)SDA=1; //判断发送位
else SDA=0;
_Nop();
SCL=1; //置时钟线为高,通知被控器开始接收数据位
_Nop();
_Nop(); //保证时钟高电平周期大于4μ
_Nop();
_Nop();
_Nop();
SCL=0;
}
_Nop();
_Nop();
SDA=1; //8位发送完后释放数据线,准备接收应答位
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)ack=0;
else ack=1; //判断是否接收到应答信号
SCL=0;
_Nop();
_Nop();
} /*----------------------------------------------------------------
字节数据传送函数
函数原型: unsigned char RcvByte();
功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数。
------------------------------------------------------------------*/
unsigned char RcvByte()
{
unsigned char retc;
unsigned char BitCnt;
retc=0;
SDA=1; //置数据线为输入方式
for(BitCnt=0;BitCnt<8;BitCnt++)
{
_Nop();
SCL=0; //置时钟线为低,准备接收数据位
_Nop();
_Nop(); //时钟低电平周期大于4.7us
_Nop();
_Nop();
_Nop();
SCL=1; //置时钟线为高使数据线上数据有效
_Nop();
_Nop();
retc=retc<<1;
if(SDA==1)retc=retc+1; //读数据位,接收的数据位放入retc中
_Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
return(retc);
} /*----------------------------------------------------------------
应答子函数
原型: void Ack_I2c(void);
----------------------------------------------------------------*/
void Ack_I2c(void)
{
SDA=0;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); //时钟低电平周期大于4μ
_Nop();
_Nop();
_Nop();
SCL=0; //清时钟线,钳住I2C总线以便继续接收
_Nop();
_Nop();
}/*----------------------------------------------------------------
向有子地址器件发送多字节数据函数
函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
如果返回1表示操作成功,否则操作有误。
注意: 使用前必须已结束总线。
----------------------------------------------------------------*/
bit ISendStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i;
for(i=0;i<no;i++)
{
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(suba); //发送器件子地址
if(ack==0)return(0);
SendByte(*s); //发送数据
if(ack==0)return(0);
Stop_I2c(); //结束总线
DelayMs(1); //必须延时等待芯片内部自动处理数据完毕
s++;
suba++;
}
return(1);
}/*----------------------------------------------------------------
向无子地址器件读字节数据函数
函数原型: bit IRcvByte(unsigned char sla,ucahr *c);
功能: 从启动总线到发送地址,读数据,结束总线的全过程,从器件地
址sla,返回值在c.
如果返回1表示操作成功,否则操作有误。
注意: 使用前必须已结束总线。
----------------------------------------------------------------*/
/*bit IRcvByte(unsigned char sla,unsigned char *c)
{
Start_I2c(); //启动总线
SendByte(sla+1); //发送器件地址
if(ack==0)return(0);
*c=RcvByte(); //读取数据
NoAck_I2c(); //发送非就答位
Stop_I2c(); //结束总线
return(1);
}*/
/*----------------------------------------------------------------
向有子地址器件读取多字节数据函数
函数原型: bit ISendStr(unsigned char sla,unsigned char suba,ucahr *s,unsigned char no);
功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
如果返回1表示操作成功,否则操作有误。
注意: 使用前必须已结束总线。
----------------------------------------------------------------*/
bit IRcvStr(unsigned char sla,unsigned char suba,unsigned char *s,unsigned char no)
{
unsigned char i; Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(suba); //发送器件子地址
if(ack==0)return(0); Start_I2c();
SendByte(sla+1);
if(ack==0)return(0); for(i=0;i<no-1;i++)
{
*s=RcvByte(); //发送数据
Ack_I2c(); //发送就答位
s++;
}
*s=RcvByte();
NoAck_I2c(); //发送非应位
Stop_I2c(); //结束总线
return(1);
}
Ⅲ 请问AVRmega16单片机上面的IIC总线提到的SLA+R/W是指的是什么啊
SLA+R/W 共八位
SLA:前七位,表示从机地址(所以最多支持128个从设备)
R/W:最后一位,为READ/WRITE控制位;如果READ/WRITE 为1,则执行读操作;否则执行写操作。
Ⅳ 具体怎么样用单片机控制步进电机的转速
也许不是程序的问题,而是电机转动惯量大,当驱动时间小于某一数值,则不能完成一个步进。表现为卡住。
能把电机转的更快的出路:
1.从程序上:起动时转速是逐步加速,停止时转速是逐步减速,即不要从静止一下子加到2.2ms。
2.从机械上,电机与被驱动物之间加弹性联接,得以缓冲。
3.从电气驱动上,采用双电压驱动,以加快驱动(激磁)电流的建立。
Ⅳ 单片机i2c总线编程,
return 一旦执行,就退出函数了。
也就是说 如果flag==0 那么就return0 后面的就不执行了,退出函数
Ⅵ 关于51单片机的小问题
运用IIC总线和串口通信 ,给你两个例子参考
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define AddWr 0xa0 //器件地址选择及写标志
#define AddRd 0xa1 //器件地址选择及读标志
/*有关全局变量*/
sbit Sda= P3^7; //串行数据
sbit Scl= P3^6; //串行时钟
sbit WP= P3^5; //硬件写保护
uchar outdata[4]; //定义发送的字节数
uchar indata[4];
uchar count, count_r=0;
SendData(uchar *a)
{
outdata[0] = a[0];
outdata[1] = a[1];
outdata[2] = a[2];
outdata[3] = a[3];
count = 1;
SBUF=outdata[0];
}
void mDelay(uchar j)
{
uchar i;
for(;j>0;j--)
for(i=0;i<125;i--);
}
/*起始*/
void Start(void)
{
Sda=1;
Scl=1;
_nop_();_nop_();_nop_();_nop_();
Sda=0;
_nop_();_nop_();_nop_();_nop_();
}
/*停止*/
void Stop(void)
{
Sda=0;
Scl=1;
_nop_();_nop_();_nop_();_nop_();
Sda=1;
_nop_();_nop_();_nop_();_nop_();
}
/*应答*/
void Ack(void)
{
Sda=0;
_nop_();_nop_();_nop_();_nop_();
Scl=1;
_nop_();_nop_();_nop_();_nop_();
Scl=0;
}
/*反向应答位*/
void NoAck(void)
{
Sda=1;
_nop_();_nop_();_nop_();_nop_();
Scl=1;
_nop_();_nop_();_nop_();_nop_();
Scl=0;
}
/*发送数据子程序,Data为要求发送的数据*/
void Send(uchar Data)
{
uchar BitCounter=8; //位数控制
uchar temp; //中间变量控制
do
{
temp=Data;
Scl=0;
_nop_();_nop_();_nop_();_nop_();
if((temp&0x80)==0x80) //如果最高位是1
Sda=1;
else
Sda=0;
Scl=1;
temp=Data<<1; //RLC
Data=temp;
BitCounter--;
}while(BitCounter);
Scl=0;
}
/*读一个字节的数据,并返回该字节值*/
uchar Read(void)
{
uchar temp=0;
uchar temp1=0;
uchar BitCounter=8;
Sda=1;
do{
Scl=0;
_nop_();_nop_();_nop_();_nop_();
Scl=1;
_nop_();_nop_();_nop_();_nop_();
if(Sda) //如果Sda=1
temp=temp|0x01; //temp的最低位置1
else
temp=temp&0xfe; //否则temp的最低位清0
if(BitCounter-1)
{
temp1=temp<<1;
temp=temp1;
}
BitCounter--;
}while(BitCounter);
return(temp);
}
//写入多个字节。
void WrToROMs(uchar *iData,uchar Address,uchar Num)
{
uchar i;
Start(); //发送启动信号
Send(0xa0); //发送SLA+W
Ack();
Send(Address); //发送地址
Ack();
for(i=0;i<Num;i++)
{
Send(iData[i]);
Ack();
}
Stop();
mDelay(4); //延时4ms。。。。
}
void RdFromROM(uchar Data[],uchar Address,uchar Num)
{
uchar i;
uchar *PData;
PData=Data;
for(i=0;i<Num;i++)
{
Start();
Send(0xa0);
Ack();
Send(Address+i);
Ack();
Start();
Send(0xa1);
Ack();
*(PData+i)=Read();
Scl=0;
NoAck();
Stop();
}
}
void main()
{
uchar Number[4]={1,2,3,4};
/* 系统初始化 */
TMOD = 0x20; //定时器T1使用工作方式2
TH1 = 253; // 设置初值
TL1 = 253;
TR1 = 1; // 开始计时
SCON = 0x50; //工作方式1,波特率9600bps,允许接收
ES = 1;
EA = 1; // 打开所有中断
TI = 0;
RI = 0;
WP= 1;
WrToROMs(Number,4,4); //将初始化后的数值写入EEPROM
mDelay(20);
Number[0]=0;
Number[1]=0;
Number[2]=0;
Number[3]=0; //将数组中的值清掉,以验证读出的数是否正确
RdFromROM(Number,4,4);
SendData(Number) ; //发送到串口。
while(1);
}
void RSINTR() interrupt 4 using 2
{
uchar InPut3;
if(TI==1)
{
TI=0;
if(count!=4)
{
SBUF= outdata[count];
count++;
}
}
if(RI==1)
{
InPut3=SBUF;
if(InPut3==90) //判断起始位
count_r=0;
indata[count_r]=InPut3;
count_r++;
RI=0;
if (count_r==4)
{
//数据接收完毕处理。
}
}
}
---------------------------------------------------------------------
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar outdata[5]; //定义发送的字节数
uchar indata[4];
uchar count, count_r=0;
SendData(uchar *a)
{
outdata[0] = a[0];
outdata[1] = a[1];
outdata[2] = a[2];
outdata[3] = a[3];
outdata[4] = a[4];
count = 1;
SBUF=outdata[0];
}
void main()
{
uchar str[6]={""};
/* 系统初始化 */
TMOD = 0x20; //定时器T1使用工作方式2
TH1 = 253; // 设置初值
TL1 = 253;
TR1 = 1; // 开始计时
SCON = 0x50; //工作方式1,波特率9600bps,允许接收
ES = 1;
EA = 1; // 打开所以中断
TI = 0;
RI = 0;
SendData(str) ; //发送到串口。
while(1);
}
void RSINTR() interrupt 4 using 2
{
uchar InPut3;
if(TI==1) //发送中断
{
TI=0;
if(count!=5) //发送完5位数据
{
SBUF= outdata[count];
count++;
}
}
if(RI==1) //接收中断
{
InPut3=SBUF;
indata[count_r]=InPut3;
count_r++;
RI=0;
if (count_r==4)//接收完4位数据
{
//数据接收完毕处理。
count_r=0;
P0 = indata[3];
}
}
}
Ⅶ 51单片机如何模拟I2C总线中从机接收ID,发送数据的程序
#include /*头文件的包含*/
#include
#define uchar unsigned char /*宏定义*/
#define uint unsigned int
/*端口位定义*/
sbit BELL_OUT=P3^5;
sbit SCL="P1"^3;/*模拟I2C数据传送位*/
sbit SDA="P1"^4;/*模拟I2C时钟控制位*/
bit ack; /*应答标志位*/
/*********************************************************************
起动总线函数
函数原型: void Start_I2c();
功能:启动I2C总线,即发送I2C起始条件
********************************************************************/
void Start_I2c()
{
SDA="1"; /*发送起始条件的数据信号*/
_nop_();
SCL="1"; /*起始条件建立时间大于4.7us,延时*/
_nop_();
SDA="0"; /*发送起始信号*/
_nop_(); /* 起始条件锁定时间大于4μs*/
SCL="0"; /*钳住I2C总线,准备发送或接收数据 */
_nop_();
}
/***********************************************
结束总线函数
函数原型: void Stop_I2c();
功能:结束I2C总线,即发送I2C结束条件
***********************************************/
void Stop_I2c()
{
SDA="0"; /*发送结束条件的数据信号*/
_nop_(); /*发送结束条件的时钟信号*/
SCL="1"; /*结束条件建立时间大于4μs*/
_nop_();
SDA="1"; /*发送I2C总线结束信号*/
_nop_();
}
/*******************************************************************
字节数据传送函数
函数原型: void SendByte(uchar c);
功能:将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对此状
态位进行操作(不应答或非应答都使ack=0 假) 。发送数据正常,ack=1;
ack=0表示被控器无应答或损坏。
********************************************************************/
void SendByte(uchar c)
{
uchar BitCnt;
for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/
{
SCL="0";
if((c<
else SDA="0";
SCL="1"; /*置时钟线为高,通知被控器开始接收数据位*/
_nop_(); /*保证时钟高电平周期大于4μs*/
}
//从机应答,可以用应答和非应答信号代替
_nop_();
SCL="0";
_nop_();
SDA="1"; //
_nop_();
SCL="1";
_nop_();
if(SDA==1){ack=0;} /*判断是否接收到应答信号*/
else ack="1";
SCL="0";
_nop_();
}
/*******************************************************************
字节数据传送函数
函数原型: uchar RcvByte();
功能:用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数。
********************************************************************/
uchar RcvByte()
{
uchar retc;
uchar BitCnt;
retc="0";
for(BitCnt=0;BitCnt<8;BitCnt++)
{
SCL="1"; /*置时钟线为高使数据线上数据有效*/
_nop_();
retc="retc"<<1;
if(SDA==1) retc="retc"+1; /*读数据位,接收的数据位放入retc中 */
SCL="0";
}
return(retc);
}
/********************************************************************
应答子函数
原型: void Ack_I2c();
功能:主控器进行应答信号
********************************************************************/
void Ack_I2c()
{
SDA="0"; /*在此发出应答信号 */
_nop_();
SCL="0";
_nop_();
SCL="1";
_nop_();
SCL="0"; /*清时钟线,钳住I2C总线以便继续接收*/
_nop_();
SDA="1";
_nop_();
}
/********************************************************************
非应答子函数
原型: void NoAck_I2c();
功能:主控器进行非应答信号
********************************************************************/
void NoAck_I2c()
{
SDA="1"; /*在此发出非应答信号 */
_nop_();
SCL="1";
_nop_();
SCL="0"; /*清时钟线,钳住I2C总线以便继续接收*/
}
/*******************************************************************
向无子地址器件发送字节数据函数
函数原型: bit ISendByte(uchar sla,ucahr c);
功能:从启动总线到发送地址,数据,结束总线的全过程,从器件地址sla。如果
返回1表示操作成功,否则操作有误。
********************************************************************/
bit ISendByte(uchar sla,uchar c)
{
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(c); /*发送数据*/
if(ack==0)return(0);
Stop_I2c(); /*结束总线*/
return(1);
}
/*******************************************************************
向有子地址器件发送多字节数据函数
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能:从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件地址sla,
子地址suba,发送内容是s指向的内容,发送no个字节。如果返回1表示
操作成功,否则操作有误。
********************************************************************/
bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar i;
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器件子地址*/
if(ack==0)return(0);
for(i=0;i
{
SendByte(*s); /*发送数据*/
if(ack==0)return(0);
s++;
}
Stop_I2c(); /*结束总线*/
//delayMs(1); //
return(1);
}
/*******************************************************************
向无子地址器件读字节数据函数
函数原型: bit IRcvByte(uchar sla,ucahr *c);
功能:从启动总线到发送地址,读数据,结束总线的全过程,从器件地址sla,返
回值在c。如果返回1表示操作成功,否则操作有误。
********************************************************************/
bit IRcvByte(uchar sla,uchar *c)
{
Start_I2c(); /*启动总线*/
SendByte(sla+1); /*发送器件地址*/
if(ack==0)return(0);
*c=RcvByte(); /*读取数据*/
NoAck_I2c(); /*发送非就答位*/
Stop_I2c(); /*结束总线*/
return(1);
}
/**********************************************************************
向有子地址器件读取多字节数据函数
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能:从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件地址sla,
子地址suba,读出的内容放入s指向的存储区,读no个字节。如果返回1
表示操作成功,否则操作有误。
**********************************************************************/
bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
{
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器件子地址*/
if(ack==0)return(0);
Start_I2c();
SendByte(sla+1);
if(ack==0)return(0);
while(no!=1)
{
*s=RcvByte();/*发送数据*/
Ack_I2c(); /*发送就答位*/
s++;
no--;
}
*s=RcvByte();
NoAck_I2c(); /*发送非应位*/
Stop_I2c(); /*结束总线*/
return(1);
}
Ⅷ 51单片机通过三极管 驱动继电器加热 2000w的电热丝接220V 选用什么型号的继电器给个电路图及详细解释
SLA-12VDC-SL-A继电器(30A) 5脚30A的继电器 价格便宜 三块钱上下 三极管 用SS8050或SS8550吧 或者组成达林顿管用 9012的电流太小 不推荐(驱动继电器别忘了加续流二极管)
Ⅸ 单片机中 IRcvStr()是做什么的
太神奇了,你就截了这样一段,谁知道这是干什么用的,
这里开了定时器中断,你看中断服务函数里面是什么内容就知道是做什么用了;
IRcvStr,是IIC头文件里的一个子函数,你搜一下就可以找到
向有子地址器件读取多字节数据函数
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
如果返回1表示操作成功,否则操作有误。
注意: 使用前必须已结束总线。
bit ISendStr(uchar sla,uchar suba,uchar *s,uchar no)
在下面的头文件里也可以找到;
即使前面有这样的定义,也要有这个函数的原型,或许在本身C文件里,或者在前面包含的头文件里,如#include"",#include<>
I2C的头文件
===================================================
bit ack; /*应答标志位*/
/*定义空指令*/
void _Nop(){
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
}
/*******************************************************************
起动总线函数
函数原型: void Start_I2c();
功能: 启动I2C总线,即发送I2C起始条件.
********************************************************************/
void Start_I2c()
{
SDA=1; /*发送起始条件的数据信号*/
_Nop();
SCL=1;
_Nop(); /*起始条件建立时间大于4.7us,延时*/
_Nop();
_Nop();
_Nop();
_Nop();
SDA=0; /*发送起始信号*/
_Nop(); /* 起始条件锁定时间大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
SCL=0; /*钳住I2C总线,准备发送或接收数据 */
_Nop();
_Nop();
}
/*******************************************************************
结束总线函数
函数原型: void Stop_I2c();
功能: 结束I2C总线,即发送I2C结束条件.
********************************************************************/
void Stop_I2c()
{
SDA=0; /*发送结束条件的数据信号*/
_Nop(); /*发送结束条件的时钟信号*/
SCL=1; /*结束条件建立时间大于4μs*/
_Nop();
_Nop();
_Nop();
_Nop();
_Nop();
SDA=1; /*发送I2C总线结束信号*/
_Nop();
_Nop();
_Nop();
_Nop();
}
/*******************************************************************
字节数据传送函数
函数原型: void SendByte(uchar c);
功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对
此状态位进行操作.(不应答或非应答都使ack=0 假)
发送数据正常,ack=1; ack=0表示被控器无应答或损坏。
********************************************************************/
void SendByte(uchar c){
uchar BitCnt;
for(BitCnt=0;BitCnt <8;BitCnt++){ /*要传送的数据长度为8位*/
if((c < <BitCnt) & 0x80)
SDA=1; /*判断发送位*/
else
SDA=0;
_Nop();
SCL=1; /*置时钟线为高,通知被控器开始接收数据位*/
_Nop();
_Nop(); /*保证时钟高电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0;
}
_Nop();
_Nop();
SDA=1; /*8位发送完后释放数据线,准备接收应答位*/
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop();
_Nop();
if(SDA==1)
ack=0;
else
ack=1; /*判断是否接收到应答信号*/
SCL=0;
_Nop();
_Nop();
}
/*******************************************************************
字节数据传送函数
函数原型: uchar RcvByte();
功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号),
发完后请用应答函数。
********************************************************************/
uchar RcvByte()
{
uchar retc;
uchar BitCnt;
retc=0;
SDA=1; /*置数据线为输入方式*/
for(BitCnt=0;BitCnt <8;BitCnt++)
{
_Nop();
SCL=0; /*置时钟线为低,准备接收数据位*/
_Nop();
_Nop(); /*时钟低电平周期大于4.7μs*/
_Nop();
_Nop();
_Nop();
SCL=1; /*置时钟线为高使数据线上数据有效*/
_Nop();
_Nop();
retc=retc < <1;
if(SDA==1)
retc=retc+1; /*读数据位,接收的数据位放入retc中 */
_Nop();
_Nop();
}
SCL=0;
_Nop();
_Nop();
return(retc);
}
/********************************************************************
应答子函数
原型: void Ack_I2c(bit a);
功能:主控器进行应答信号,(可以是应答或非应答信号)
********************************************************************/
void Ack_I2c(bit a)
{
if(a==0)
SDA=0; /*在此发出应答或非应答信号 */
else
SDA=1;
_Nop();
_Nop();
_Nop();
SCL=1;
_Nop();
_Nop(); /*时钟低电平周期大于4μs*/
_Nop();
_Nop();
_Nop();
SCL=0; /*清时钟线,钳住I2C总线以便继续接收*/
_Nop();
_Nop();
}
/*******************************************************************
向有子地址器件发送多字节数据函数
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能: 从启动总线到发送地址,子地址,数据,结束总线的全过程,从器件
地址sla,子地址suba,发送内容是s指向的内容,发送no个字节。
如果返回1表示操作成功,否则操作有误。
注意: 使用前必须已结束总线。
********************************************************************/
bit ISendStr(uchar sla,uchar suba, uchar *s,uchar no)
{
uchar i, *tmp;
tmp=&i;
Start_I2c(); //启动总线
SendByte(sla); //发送器件地址
if(ack==0)return(0);
SendByte(suba); //发送器件子地址
if(ack==0)return(0);
for(i=0;i <no;i++)
{
SendByte(*s); //发送数据
if(ack==0)return(0);
s++;
}
Stop_I2c(); //结束总线
return(1);
}
/*******************************************************************
向有子地址器件读取多字节数据函数
函数原型: bit ISendStr(uchar sla,uchar suba,ucahr *s,uchar no);
功能: 从启动总线到发送地址,子地址,读数据,结束总线的全过程,从器件
地址sla,子地址suba,读出的内容放入s指向的存储区,读no个字节。
如果返回1表示操作成功,否则操作有误。
注意: 使用前必须已结束总线。
********************************************************************/
bit IRcvStr(uchar sla,uchar suba,uchar *s,uchar no)
{
uchar i;
Start_I2c(); /*启动总线*/
SendByte(sla); /*发送器件地址*/
if(ack==0)return(0);
SendByte(suba); /*发送器件子地址*/
if(ack==0)return(0);
Start_I2c();
SendByte(sla+1);
if(ack==0)return(0);
for(i=0;i <no-1;i++)
{
*s=RcvByte(); /*发送数据*/
Ack_I2c(0); /*发送就答位*/
s++;
}
*s=RcvByte();
Ack_I2c(1); /*发送非应位*/
Stop_I2c(); /*结束总线*/
return(1);
}
/*******************************************************************
写入结束检测
********************************************************************/
bit Iwcheck(uchar sla)
{
Start_I2c(); //*启动总线
SendByte(sla); //*发送器件地址
if(ack==0)return(0);
//SendByte(c); //*发送数据
// if(ack==0)return(0);
Stop_I2c(); //*结束总线
return(1);
}
=======================================
#define A_Data 0x10 //Data在EEPROM中的地址
uchar Data; //一字节数据
写入一字节
if(!ISendStr(0xA0,A_Data,&Data,1))
return FALSE;
return TRUE
if(!IRcvStr(0xA0,A_Data,&Data,1))
return FALSE;
return TRUE;
Ⅹ 关于AVR单片机引用头文件slavr.h的问题
这个H文件应该不是你的编译器自带的文件,所以不是很清楚,就原理而言,你如果要驱动液晶,那么和液晶连接的几个引脚是一定要进行初始化配置的,在你的H文件里一定有定义,比如#DEFINE这样的语句,这样就把你和液晶连接的几个引脚用你自己定义的名称联系起来了,在根据硬件的连接方式,把DEFINE后面的相应引脚改成适合你硬件的引脚名称。比如#DEFINE CS PORTA.7,你的电路里CS用的事PORTA.6,那么你直接把DEFINE后面的PORTA.7改成PORTA.6就可以了,在你的C程序中还是照样用CS作为你的名字,整个C也不用做修改.(只是举个例子,在你的编译器里可能不能识别这样的位定义,那就要用其它方法进行表示)
如果按照你的说法,那就要自己定义了,其实就是改一个名字就OK了,很容易!看一些单片机相关的程序就明白了