基于STC15F104W的单片机示波器
代码如下,利用PCF8591和iic采集模拟信号然后通过iic接口的OLED显示出来
代码不完善有BUG,望大神斧正!
这个示波器推荐输入电压0-5V,显示的时候右上角会显示实时电压(单位毫伏)
但是由于前置硬件的存在输入超过5V的电压甚至是负电压也是可以的,但是超过±5V的电压会被钳位二极管钳住到±5V
主要思路还是画点函数画出图像
这段代码我是直接抄B站UP主@x麟枫 的作业的,比较懒23333
void Setpos(unsigned char x0,unsigned char y0)
{
unsigned char y,mod,pos;
if(y0%8==0){ //输入的y进行处理,如果能被8整除,值必然在0~7页
y=y0/8; //设它的点在对应值的第一个点。
pos = 0x01;
}
else{
y = y0/8; //如果不能被整除
mod = y0%8; //取余数,用把余数看成1~7个二进制位
//然后用16进制在那一页上设立对应的值
switch(mod)
{
case 1:
pos = 0x02;
break;
case 2:
pos = 0x04;
break;
case 3:
pos = 0x08;
break;
case 4:
pos = 0x10;
break;
case 5:
pos = 0x20;
break;
case 6:
pos = 0x40;
break;
case 7:
pos = 0x80;
break;
default:
break;
}
}
oled_set_pos(x0,y); //OLED设置起始位置的函数
oled_wr_byte(pos,1); //在那个位置写数据,1表示那个点亮,0表示那个点灭
}
然后主代码如下:
#include<stc15.h> //包含单片机寄存器的头文件
#include <I2C.H>
#define uchar unsigned char
#define PCF8591 0x90 //PCF8591 地址
int xx=0;int y11,y22;
// 变量定义
unsigned char AD_CHANNEL;
unsigned int D[32];
int ii,hh;
// 函数申明
void delay(uchar i);
bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val);
bit ISendByte(unsigned char sla,unsigned char c);
unsigned char IRcvByte(unsigned char sla);
//******************************************************************/
int main()
{
oled_init();//初始化
/*oled_wr_byte(0x2e,0);//关滚动
oled_showstring(0,0,"TM VALUE",16);
oled_showstring(0,2,"PR VALUE",16);
oled_showstring(0,4,"NO VALUE",16);
oled_showstring(0,6,"AR VALUE",16);*/
while(1)
{
oled_DrawLine(0,0,0,63);
oled_DrawLine(0,63,127,63);
/********以下AD-DA处理*************/
for(xx=0;xx<128;xx++)
{
switch(AD_CHANNEL)
{
case 0: ISendByte(PCF8591,0x41);
D[0]=IRcvByte(PCF8591); //ADC0 模数转换1 光敏电阻
break;
case 1: ISendByte(PCF8591,0x42);
D[1]=IRcvByte(PCF8591); //ADC1 模数转换2 热敏电阻
break;
case 2: ISendByte(PCF8591,0x43);
D[2]=IRcvByte(PCF8591); //ADC2 模数转换3 输入端
break;
case 3: ISendByte(PCF8591,0x40);
D[3]=IRcvByte(PCF8591); //ADC3 模数转换4 可调0-5v
break;
case 4: DACconversion(PCF8591,0x40, D[4]); //DAC 数模转换
break;
}
D[4]=D[2];//把模拟输入采样的信号 通过数模转换输出
if(++AD_CHANNEL>4) AD_CHANNEL=0;
ii=map(D[2],0,255,63,9);
hh=map(D[2],0,255,0,5000);
/********以下将AD的值通过OLED显示*************/
oled_shownum(64,0,hh,4,32);
//oled_shownum(80,1,ii,3,32);
Setpos(xx,ii);
delay(200);
}
oled_clear();
}
}
void delay(uchar i)
{
uchar j,k;
for(j=i;j>0;j--)
for(k=125;k>0;k--);
}
/*******************************************************************
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);
}