先上参考
【蓝桥杯单片机入门】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演示视频