蓝桥杯单片机笔记——PCF8591

先上参考

【蓝桥杯单片机入门】11.PCF8591芯片(硬件介绍+软件编程)

输出模拟电压值的函数步骤

读取当前的电压的函数步骤

这是对应的函数

void pcf_dw(u8 dat){//输出电压函数
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x40);
	I2CWaitAck();
	I2CSendByte(dat);
	I2CWaitAck();
	I2CStop();
}

u8 pcf_dr(u8 channel){//读取电压函数
	u8 dat;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(channel);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	dat=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return dat;
}

我自己写了一些模块化函数 大家可以参考以下 可以用chatgpt写一下注释 如果哪里看不懂

当然可以评论区留言 我看到我会回复的

iic.c

/*	#   I2C代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include "main.h"
sbit scl=P2^0;
sbit sda=P2^1;
#define DELAY_TIME	5

//
static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();		
    }
    while(n--);      	
}

//
void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}

//
void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

//
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}

void pcf_dw(u8 dat){
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x40);
	I2CWaitAck();
	I2CSendByte(dat);
	I2CWaitAck();
	I2CStop();
}

u8 pcf_dr(u8 channel){
	u8 dat;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(channel);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	dat=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return dat;
}

iic.h

#ifndef __IIC_H
#define __IIC_H

#include "main.h"

static void I2C_Delay(unsigned char n);
void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);
void pcf_dw(u8 dat);
u8 pcf_dr(u8 channel);

#endif

smg.c

#include "main.h"

u8 code smg_duanma[18]={
	0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
	0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
	0xbf,0x7f};

void selecthc573(u8 channel){
	switch(channel){
		case 4:
			P2=(P2&0x1f)|0x80;
		break;
		case 5:
			P2=(P2&0x1f)|0xa0;
		break;
		case 6:
			P2=(P2&0x1f)|0xc0;
		break;
		case 7:
			P2=(P2&0x1f)|0xe0;
		break;
	}
}
void smg_display(u8 pos,u8 value){
	selecthc573(6);
	P0=0x01<<pos;
	selecthc573(7);
	P0=0xff;
	P0=value;
}
void smg_clear(){
	int n;
	for(n=0;n<8;n++){
	smg_display(n,0xff);
	}
}

smg.h

#ifndef __SMG_H
#define __SMG_H

#include "main.h"

void smg_display(u8 pos,u8 value);
void selecthc573(u8 channel);
void smg_clear();

extern u8 code smg_duanma[18];
#endif

key.c

#include "main.h"

sfr P4=0xc0;

sbit s7r1=P3^0;
sbit s6r2=P3^1;
sbit s5r3=P3^2;
sbit s4r4=P3^3;
sbit c4=P3^4;
sbit c3=P3^5;
sbit c2=P4^2;
sbit c1=P4^4;
#define yan 20000
u8 keyb=0;

void scanmulkey(){
//row1
	s7r1=0;
	s6r2=s5r3=s4r4=1;
	c1=c2=c3=c4=1;
	if(c1==0){
		delay(yan);
		if(c1==0){
			while(c1==0);
			keyb=7;
		}
	}
	if(c2==0){
		delay(yan);
		if(c2==0){
			while(c2==0);
			keyb=11;
		}
	}
	if(c3==0){
		delay(yan);
		if(c3==0){
			while(c3==0);
			keyb=15;
		}
	}
	if(c4==0){
		delay(yan);
		if(c4==0){
			while(c4==0);
			keyb=19;
		}
	}
//row2
	s6r2=0;
	s7r1=s5r3=s4r4=1;
	c1=c2=c3=c4=1;
	if(c1==0){
		delay(yan);
		if(c1==0){
			while(c1==0);
			keyb=6;
		}
	}
	if(c2==0){
		delay(yan);
		if(c2==0){
			while(c2==0);
			keyb=10;
		}
	}
	if(c3==0){
		delay(yan);
		if(c3==0){
			while(c3==0);
			keyb=14;
		}
	}
	if(c4==0){
		delay(yan);
		if(c4==0){
			while(c4==0);
			keyb=18;
		}
	}
//row3
	s5r3=0;
	s7r1=s6r2=s4r4=1;
	c1=c2=c3=c4=1;
	if(c1==0){
		delay(yan);
		if(c1==0){
			while(c1==0);
			keyb=5;
		}
	}
	if(c2==0){
		delay(yan);
		if(c2==0){
			while(c2==0);
			keyb=9;
		}
	}
	if(c3==0){
		delay(yan);
		if(c3==0){
			while(c3==0);
			keyb=13;
		}
	}
	if(c4==0){
		delay(yan);
		if(c4==0){
			while(c4==0);
			keyb=17;
		}
	}
//row4
	s4r4=0;
	s7r1=s6r2=s5r3=1;
	c1=c2=c3=c4=1;
	if(c1==0){
		delay(yan);
		if(c1==0){
			while(c1==0);
			keyb=4;
		}
	}
	if(c2==0){
		delay(yan);
		if(c2==0){
			while(c2==0);
			keyb=8;
		}
	}
	if(c3==0){
		delay(yan);
		if(c3==0){
			while(c3==0);
			keyb=12;
		}
	}
	if(c4==0){
		delay(yan);
		if(c4==0){
			while(c4==0);
			keyb=16;
		}
	}
}

void scanalokey(){
	if(s7r1==0){
		delay(yan);
		if(s7r1==0){
			keyb=7;
		}
	}
	if(s6r2==0){
		delay(yan);
		if(s6r2==0){
			keyb=6;
		}
	}
	if(s5r3==0){
		delay(yan);
		if(s5r3==0){
			keyb=5;
		}
	}
	if(s4r4==0){
		delay(yan);
		if(s4r4==0){
			keyb=4;
		}
	}
}


key.h

#ifndef __KEY_H
#define __KEY_H

#include "main.h"

extern u8 keyb;
void scanmulkey();
void scanalokey();
#endif

mian.c

#include "main.h"

void delay(u16 t){
	t*=12;
	while(t--);
}
u8 channel=0x03,ad=0;
u16 analog;
bit v_flag=0;
void init_t0(){//初始化定时器函数
	TMOD=0x01;//设置定时器模式 这个是16位定时器 手动装载初值
	TH0=(65536-5000)/256;//设置初值 转换成16进制 存放高位
	TL0=(65536-5000)%256;//低位
	
	ET0=1;//允许定时器0中断
	EA=1;//总中断开关
	TR0=1;//定时器!启动!!!!
}
unsigned char count=0;
void servicetimer0() interrupt 1{// 定时中断函数的标志 不可以忘记写
	TH0=(65536-1000)/256;//因为不会自动装载初值 所以需要手动装载
	TL0=(65536-1000)%256;
	if(count%100==0){v_flag=1;}//100ms测量一次
	count%=1000;
}
void pcf_smgshow(){
		smg_display(0,smg_duanma[16]);
		delay(50);
		smg_display(1,smg_duanma[channel]);
		delay(50);
		smg_display(2,smg_duanma[16]);
		delay(50);
		smg_display(5,smg_duanma[analog/100]-0x80);
		delay(50);
		smg_display(6,smg_duanma[analog/10%10]);
		delay(50);
		smg_display(7,smg_duanma[analog%10]);
		delay(50);
}
void change(){
	if(keyb==7){
		channel=0x01;
	}
	if(keyb==6){
		channel=0x03;
	}
	if(v_flag==1){
		v_flag=0;
		ad=pcf_dr(channel);
		analog=(int)(ad/255.0*5*100);
		pcf_dw(ad);
	}
}
void main(){
	init_t0();
	selecthc573(4);
	P2=0xff;
	while(1){
		scanalokey();
		change();
		pcf_smgshow();
	}

}

main.h

#ifndef __MAIN_H
#define __MAIN_H
typedef unsigned char u8;
typedef unsigned int u16;

#include <reg52.h>
#include "iic.h"
#include "intrins.h"
#include "smg.h"
#include "key.h"
void delay(u16 t);

#endif

效果演示

PCF8591演示视频

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值