/**********************51单片机学习例程************************
* 平台:Keil U4 + STC89C52
* 名称: PCF8591 ,固定输出10Hz的正弦波,数码管显示频率
* 编写:Tony
* 日期:2022-2-12
* 晶体:12MHZ
* 变更记录:无
******************************************************************/
#include <reg52.h>
#define GPIO_DIG P1 //数码管使用的段选IO
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4; //138译码器,数码管的位选
#define GE {LSA=1;LSB=1;LSC=1;} //打开个位位选端
#define SHI {LSA=0;LSB=1;LSC=1;} //打开十位位选端
#define uchar unsigned char
#define uint unsigned int
uchar code DIG_CODE[] = {
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar num_ge,num_shi;
uchar SEG_CNT;
uchar code sin_table[] = {0x7F,0x98,0xB0,0xC6,0xD9,0xE9,0xF5,0xFC,
0xFE,0xFC,0xF5,0xE9,0xD9,0xC6,0xB0,0x98,
0x7F,0x66,0x4E,0x38,0x25,0x15,0x09,0x02,
0x00,0x02,0x09,0x15,0x25,0x38,0x4E,0x66};
//正弦波数据表
uint timer0_value; //定时器0初值寄存器
uchar vol_num; //数组标号
uchar TH0_BUFF; //TH0装载值的暂存器
uchar TL0_BUFF; //TL0装载值的暂存器
void Timer0_Init(void);
void SEG_display(void);
extern void DAC_OUT_START(void); //调用其它文件中的函数
extern bit send_byte(uchar DAT);
/***************************************************
* 定时器0初始化子函数
* 根据定时器初值初始化定时器0
****************************************************/
void Timer0_Init(void)
{
TMOD=0x01; //使用定时器1,16位定时器
TH0_BUFF=(65535-timer0_value)/256;
TL0_BUFF=(65535-timer0_value)%256;
TH0=TH0_BUFF;
TL0=TL0_BUFF;
TF0=0; //清中断标志
EA=1; //开总中断
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
}
/***************************************************
* 中断子程序,1/32个周期中断一次
* DA输出电压值,同时给TH0和TL0赋初值
****************************************************/
void Time0() interrupt 1
{
TH0=TH0_BUFF;
TL0=TL0_BUFF;
send_byte(sin_table[vol_num]);//送入要转换的电压值
if(vol_num>=31) //电压值更新
vol_num=0;
else
vol_num++;
}
void SEG_display(void)
{
switch(SEG_CNT)
{
case 0x01: GPIO_DIG=0x00; SHI; GPIO_DIG= DIG_CODE[1];
SEG_CNT++; break;
case 0x02: GPIO_DIG=0x00; GE; GPIO_DIG= DIG_CODE[0];
SEG_CNT=0x01;break;
default: break;
}
}
void main()
{
SEG_CNT=0x01;
timer0_value=3125-37; //补偿37
DAC_OUT_START();
Timer0_Init();
while(1)
{
SEG_display();
}
}
#include <reg52.h>
#include <intrins.h> //包含空指令函数_nop_();
#define uchar unsigned char
#define uint unsigned int
#define delay_6us {_nop_();_nop_();_nop_();\
_nop_();_nop_();_nop_();} //延时5个机器周期
#define PCF_ADDR 0x90 //定义PCF8591的地址
sbit SCL = P3^6; //定义总线连接端口
sbit SDA = P3^7;
void IIC_start(void); //函数声明
void IIC_stop(void);
bit ack_check(void);
bit send_byte(uchar DAT);
void PCF8591_DAC_OUT(uchar DAT);
void DAC_OUT_START(void);
void DAC_OUT_STOP(unsigned char DAT);
/***************************************************
* IIC总线开始信号
****************************************************/
void IIC_start(void)
{
SDA=1;
SCL=1; //置一两条线
delay_6us ; //延时6个机器周期
SDA=0; //拉低数据线
delay_6us ;
// SCL=0; //拉低时钟线
}
/***************************************************
* IIC总线停止信号
****************************************************/
void IIC_stop(void)
{
SDA=0; //拉低数据线
SCL=1; //置一时钟线
delay_6us ;
SDA=1; //置一数据线
delay_6us ;
}
/***************************************************
* 检测IIC总线应答信号
****************************************************/
bit ack_check(void)
{
bit ack_bit; //位定义应答信号存储单元
SDA=1; //释放数据线,勾引从设备发送应答信号
delay_6us ;
SCL=1; //置一时钟线
delay_6us ;
ack_bit = SDA; //采样此时的数据线信号
SCL=0; //拉低时钟线
return ack_bit; //返回采样到的应答信号
}
/***************************************************
* 向从设备发送一个字节,
* 同时检测应答信号
****************************************************/
bit send_byte(uchar DAT)
{
uchar i;
uchar temp; //缓存寄存器
bit ack; //定义位变量,反馈应答信号
temp = DAT; //待发送字节存入缓冲寄存器
for(i = 0;i < 8;i++) //循环发送8位数据
{
SCL = 0; //拉低时钟线
if((temp&0x80)==0x80) //判断temp的高位是0还是1
SDA=1;
else
SDA=0; //送出相应数据
delay_6us ;
SCL = 1; //拉高时钟线
temp <<=1; //待发送数据左移一位
delay_6us ;
}
SCL = 0; //拉低时钟线
ack = ack_check(); //调用应答信号检测子函数
return ack; //返回检测到的应答信号
}
/***************************************************
* DA转换子函数
* 控制DA输出电压
****************************************************/
void PCF8591_DAC_OUT(uchar DAT)
{
IIC_start();
if(send_byte(PCF_ADDR)==1)
{
IIC_stop();
return;
}
send_byte(0x40);
send_byte(DAT);
IIC_stop();
}
/***************************************************
* DA初始化子函数
****************************************************/
void DAC_OUT_START(void)
{
IIC_start();
if(send_byte(PCF_ADDR)==1)
{
IIC_stop();
return;
}
send_byte(0x40);
}
/***************************************************
* DA停止子函数
****************************************************/
void DAC_OUT_STOP(uchar DAT)
{
send_byte(DAT);
IIC_stop();
}