一、原理部分
在iic.c中增加代码
void write_adc(unsigned char add)//要用哪一个通道在调用时就写哪一个
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
}
unsigned char read_adc(unsigned char add)//和上面的用法一样
{
unsigned char temp;
EA = 0;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
EA = 1;
return temp;
}
在iic.h中增加代码
void write_adc(unsigned char add);
unsigned char read_adc(unsigned char add);
在主函数中包含头文件iic.h
iic.h
中包含stc15f2k60s2.h
在写寄存器的时候使用P2 = P2&0x1f|[对应的码值],这样可以清除写寄存器时对其他位的干扰。例如打开蜂鸣器的寄存器写为P2 = P2&0x1f|0xa0;同理 关闭寄存器的时候写成P2 = P2&0x1f。
二、代码部分
实验平台:CT107D
实验芯片:stc15f2k60s2
实验现象:数码管显示电位器1当前的电压值
代码如下
iic.h
#include "iic.h"
void Delay5us() //@12.000MHz
{
unsigned char i;
_nop_();
_nop_();
i = 12;
while (--i);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
somenop;
SDA = 0;
somenop;
SCL = 0;
}
//总线停止条件
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
somenop;
SDA = 1;
}
//应答位控制
void IIC_Ack(unsigned char ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
somenop;
SCL = 1;
somenop;
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
SCL = 0;
return 1;
}
}
//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0;i<8;i++)
{
if(byt&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
somenop;
SCL = 1;
byt <<= 1;
somenop;
SCL = 0;
}
}
//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char da;
unsigned char i;
for(i=0;i<8;i++)
{
SCL = 1;
somenop;
da <<= 1;
if(SDA)
da |= 0x01;
SCL = 0;
somenop;
}
return da;
}
void write_adc(unsigned char add)
{
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Stop();
}
//下面为自己写的
unsigned char read_adc(unsigned char add)
{
unsigned char temp;
EA = 0;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp = IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
EA = 1;
return temp;
}
iic.h
#ifndef _IIC_H
#define _IIC_H
#include "stc15f2k60s2.h"
#include "intrins.h"
#define somenop Delay5us()
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总线引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
//函数声明
void IIC_Start(void);
void IIC_Stop(void);
void IIC_Ack(unsigned char ackbit);
void IIC_SendByte(unsigned char byt);
bit IIC_WaitAck(void);
unsigned char IIC_RecByte(void);
void Delay5us();
//下面为自己写的
void write_adc(unsigned char add);
unsigned char read_adc(unsigned char add);
#endif
main.c
#include<stc15f2k60s2.h>
#include <iic.h>
#define uchar unsigned char
#define uint unsigned int
uchar duan[] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x00,0x40};
uchar disbuff[8];
uchar adc_value;
void clzbuzz()
{
P2 = P2&0x1f|0xa0;
P0 = 0xaf;
P2 = P2&0x1f;
}
void display()
{
static uchar index;
P2 = P2&0x1f|0xe0;
P0 = 0xff;
P2 = P2&0x1f;
P2 = P2&0x1f|0xc0;
P0 = 1<<index;
P2 = P2&0x1f;
P2 = P2&0x1f|0xe0;
P0 = ~duan[disbuff[index]];
P2 = P2&0x1f;
++index;
index&= 0x07;
}
void show_num()
{
disbuff[0] = 11;
disbuff[1] = 11;
disbuff[2] = 11;
disbuff[3] = 11;
disbuff[4] = 11;
disbuff[5] = adc_value/100;
disbuff[6] = adc_value/10%10;
disbuff[7] = adc_value%10;
}
void Timer0Init(void) //2毫秒@12.000MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x40; //设置定时初值
TH0 = 0xA2; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;
EA = 1;
}
void Timer0() interrupt 1
{
TL0 = 0x40; //设置定时初值
TH0 = 0xA2;
display();
}
void main()
{
clzbuzz();
Timer0Init();
write_adc(0x03);//初始化通道0x03,获取电位器1的电压值
while(1)
{
adc_value = read_adc(0x03);//读取电位器1的电压值
adc_value = adc_value*99/255.0f;//把电压值调整为0-100之间的数值
show_num();
}
}