基于stm32的ADC采集oled(IIC)显示程序代码

 这是基于stm32的ADC采集oled(IIC)显示程序代码,使用的是模拟iic,有需要的看代码自行复制

adc.h

#ifndef __O2ADC_H
#define __O2ADC_H	
#include "sys.h"

void Adc_Init(void);
u16  Get_Adc(u8 ch); 
u16 Get_Adc_Average(u8 ch,u8 times); 
 
#endif 

adc.c

 #include "o2adc.h"
 #include "delay.h"

// 
	   
		   
//初始化ADC
															   
void  Adc_Init(void)
{ 	
	ADC_InitTypeDef ADC_InitStructure; 
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1, ENABLE );	  //使能ADC1通道时钟
 

	//RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

	//PA1 作为模拟通道输入引脚                         
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;		//模拟输入引脚
	GPIO_Init(GPIOA, &GPIO_InitStructure);	

	ADC_DeInit(ADC1);  //复位ADC1 

	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//模数转换工作在单通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//模数转换工作在单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 2;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADC1, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

  
	ADC_Cmd(ADC1, ENABLE);	//使能指定的ADC1
	
	ADC_ResetCalibration(ADC1);	//使能复位校准  
	 
	while(ADC_GetResetCalibrationStatus(ADC1));	//等待复位校准结束
	
	ADC_StartCalibration(ADC1);	 //开启AD校准
 
	while(ADC_GetCalibrationStatus(ADC1));	 //等待校准结束
 
//	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能

}				  
//获得ADC值
//ch:通道值 0~3
u16 Get_Adc(u8 ch)   
{
  	//设置指定ADC的规则组通道,一个序列,采样时间
	ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 );	//ADC1,ADC通道,采样时间为239.5周期	  			    
  
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);		//使能指定的ADC1的软件转换启动功能	
	 
	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束

	return ADC_GetConversionValue(ADC1);	//返回最近一次ADC1规则组的转换结果
}

u16 Get_Adc_Average(u8 ch,u8 times)
{
	u32 temp_val=0;
	u8 t;
	for(t=0;t<times;t++)
	{
		temp_val+=Get_Adc(ch);
		delay_ms(5);
	}
	return temp_val/times;
} 	 

oled.h

#ifndef __OLED_H
#define __OLED_H	 
#include "sys.h"
#include "io_i2c.h"

#define OLED0561_ADD	0x78  // OLED的I2C地址
#define COM						0x00  // OLED寄存器地址指令
#define DAT 					0x40  // OLED 数据

void OLED0561_Init(void);//初始化
void OLED_DISPLAY_ON (void);//OLED屏开显示
void OLED_DISPLAY_OFF (void);//OLED屏关显示
void OLED_DISPLAY_LIT (u8 x);//OLED屏亮度设置(0~255)
void OLED_DISPLAY_CLEAR(void);//清屏操作
void OLED_DISPLAY_8x16(u8 x,u8 y,u16 w);//显示8x16的单个字符 
void OLED_DISPLAY_8x16_BUFFER(u8 row, u8 col, u8 *str);//显示8x16的字符串

		 				    
#endif

oled.c(模拟iic)

#include "oled0561.h"
#include "ASCII_8x16.h" //引入字体 ASCII


void OLED0561_Init (void){//OLED屏开显示初始化
	OLED_DISPLAY_OFF(); //OLED关显示
	OLED_DISPLAY_CLEAR(); //清空屏幕内容
	OLED_DISPLAY_ON(); //OLED屏初始值设置并开显示

}
void OLED_DISPLAY_ON (void){//OLED屏初始值设置并开显示
	u8 buf[28]={
	0xae,						//0xae:关显示,0xaf:开显示
  0x00,0x10,			//开始地址(双字节)       
	0xd5,0x80,			//显示时钟频率?
	0xa8,0x3f,			//复用率?
	0xd3,0x00,			//显示偏移?
	0XB0,						//写入页位置(0xB0~7)
	0x40,						//显示开始线
	0x8d,0x14,			//VCC电源
	0xa1,						//设置段重新映射?
	0xc8,						//COM输出方式?
	0xda,0x12,			//COM输出方式?
	0x81,0xff,			//对比度,指令:0x81,数据:0~255(255最高)
	0xd9,0xf1,			//充电周期?
	0xdb,0x30,			//VCC电压输出
	0x20,0x00,			//水平寻址设置
	0xa4,						//0xa4:正常显示,0xa5:整体点亮
	0xa6,						//0xa6:正常显示,0xa7:反色显示
	0xaf						//0xae:关显示,0xaf:开显示
	}; //
	I2C_SAND_BUFFER(OLED0561_ADD,COM,buf,28);
}
void OLED_DISPLAY_OFF (void){//OLED屏关显示
	u8 buf[3]={
		0xae,//0xae:关显示,0xaf:开显示
		0x8d,0x10,//VCC电源
	}; //
	I2C_SAND_BUFFER(OLED0561_ADD,COM,buf,3);
}
void OLED_DISPLAY_LIT (u8 x){//OLED屏亮度设置(0~255)
	I2C_SAND_BYTE(OLED0561_ADD,COM,0x81);
	I2C_SAND_BYTE(OLED0561_ADD,COM,x);//亮度值
}
void OLED_DISPLAY_CLEAR(void){//清屏操作
	u8 j,t;
	for(t=0xB0;t<0xB8;t++){	//设置起始页地址为0xB0
		I2C_SAND_BYTE(OLED0561_ADD,COM,t); 	//页地址(从0xB0到0xB7)
		I2C_SAND_BYTE(OLED0561_ADD,COM,0x10); //起始列地址的高4位
		I2C_SAND_BYTE(OLED0561_ADD,COM,0x00);	//起始列地址的低4位
		for(j=0;j<132;j++){	//整页内容填充
 			I2C_SAND_BYTE(OLED0561_ADD,DAT,0x00);
 		}
	}
}

//显示英文与数字8*16的ASCII码
//取模大小为16*16,取模方式为“从左到右从上到下”“纵向8点下高位”
void OLED_DISPLAY_8x16(u8  x, //显示汉字的页坐标(从0到7)(此处不可修改)
											 u8  y, //显示汉字的列坐标(从0到63)
											 u16 w){ //要显示汉字的编号
	u8 j,t,c=0;
	y=y+2; 											//因OLED屏的内置驱动芯片是从0x02列作为屏上最左一列,所以要加上偏移量
	for(t=0;t<2;t++){
		I2C_SAND_BYTE(OLED0561_ADD,COM,0xb0+x); 				//页地址(从0xB0到0xB7)
		I2C_SAND_BYTE(OLED0561_ADD,COM,y/16+0x10);		  //起始列地址的高4位
		I2C_SAND_BYTE(OLED0561_ADD,COM,y%16);						//起始列地址的低4位
		for(j=0;j<8;j++){ 															//整页内容填充
 			I2C_SAND_BYTE(OLED0561_ADD,DAT,ASCII_8x16[(w*16)+c-512]);//为了和ASII表对应要减512
			c++;}x++; 																		//页地址加1
	}
}
//向LCM发送一个字符串,长度64字符之内。
//应用:OLED_DISPLAY_8_16_BUFFER(0," DoYoung Studio"); 
void OLED_DISPLAY_8x16_BUFFER(u8 row,u8 col, u8 *str){
	//u8 r=0;
	while(*str != '\0'){
		OLED_DISPLAY_8x16(row,col*8,*str++);
		col++;
    }	
}

 /**

  * @brief  OLED_SetPos,设置光标

  * @param  x,光标x位置

    *                   y,光标y位置

  * @retval 无

  */

void OLED_SetPos(unsigned char x, unsigned char y) //设置起始点坐标

{ 

    I2C_SAND_BYTE( OLED0561_ADD, COM, (0xb0+y));

		I2C_SAND_BYTE( OLED0561_ADD, COM, ((x&0xf0)>>4)|0x10);
    
		I2C_SAND_BYTE( OLED0561_ADD, COM, (x&0x0f)|0x01);

}

模拟iic.h

#ifndef __IO_I2C_H
#define __IO_I2C_H	 
#include "sys.h"

//模拟I2C总线驱动程序//

//I2C总线速度设置
#define VL2_SPEED		2  //取值1~255,值越小速度越快(稳定性越差),默认值为2


//IO方向设置
#define VL2_SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(unsigned int)8<<28;}
#define VL2_SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(unsigned int)3<<28;}

//IO操作函数	 
#define VL2_IIC_SCL    PBout(6) 		//SCL
#define VL2_IIC_SDA    PBout(7) 		//SDA	 
#define VL2_READ_SDA   PBin(7) 		    //输入SDA 

//状态
#define STATUS_OK       0x00
#define STATUS_FAIL     0x01

//IIC操作函数
void I2C_Configuration(void);//初始化IIC的IO口

u8 I2C_SAND_BYTE(u8 address,u8 index,u8 data);              //IIC写一个8位数据
u8 I2C_SAND_BUFFER(u8 address, u8 index,u8 *pdata,u16 count);//IIC连续写

u8 I2C_READ_BYTE(u8 address,u8 index,u8 *pdata);             //IIC读一个8位数据
u8 I2C_READ_BUFFER(u8 address,u8 index,u8 *pdata,u16 count);  //IIC连续读

#endif

模拟iic.c

这段代码其实有些臃肿,可以进行优化一下

//模拟I2C总线驱动程序//

#include "delay.h"
#include "io_i2c.h"



//I2C初始化
void I2C_Configuration(void){
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//使能GPIOB时钟
	 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;  //端口配置
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;       //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //50Mhz速度
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);//PA7,PA6 输出高	

}

//产生IIC起始信号
void VL2_IIC_Start(void)
{
	VL2_SDA_OUT();//sda线输出
	VL2_IIC_SDA=1;	  	  
	VL2_IIC_SCL=1;
	delay_us(VL2_SPEED*2);
 	VL2_IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(VL2_SPEED*2);
	VL2_IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}

//产生IIC停止信号
void VL2_IIC_Stop(void)
{
	VL2_SDA_OUT();//sda线输出
	VL2_IIC_SCL=0;
	VL2_IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(VL2_SPEED*2);
	VL2_IIC_SCL=1; 
	VL2_IIC_SDA=1;//发送I2C总线结束信号
	delay_us(VL2_SPEED*2);							   	
}

//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 VL2_IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	VL2_SDA_IN();  //SDA设置为输入  
	VL2_IIC_SDA=1;delay_us(1);	   
	VL2_IIC_SCL=1;delay_us(1);	 
	while(VL2_READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			VL2_IIC_Stop();
			return 1;
		}
	}
	VL2_IIC_SCL=0;//时钟输出0 	   
	return 0;  
}

//产生ACK应答
void VL2_IIC_Ack(void)
{
	VL2_IIC_SCL=0;
	VL2_SDA_OUT();
	VL2_IIC_SDA=0;
	delay_us(VL2_SPEED);
	VL2_IIC_SCL=1;
	delay_us(VL2_SPEED);
	VL2_IIC_SCL=0;
}

//不产生ACK应答		    
void VL2_IIC_NAck(void)
{
	VL2_IIC_SCL=0;
	VL2_SDA_OUT();
	VL2_IIC_SDA=1;
	delay_us(VL2_SPEED);
	VL2_IIC_SCL=1;
	delay_us(VL2_SPEED);
	VL2_IIC_SCL=0;
}

//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void VL2_IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	VL2_SDA_OUT(); 	    
    VL2_IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
		if((txd&0x80)>>7)
			VL2_IIC_SDA=1;
		else
			VL2_IIC_SDA=0;
		txd<<=1; 	  
		delay_us(VL2_SPEED);  
		VL2_IIC_SCL=1;
		delay_us(VL2_SPEED); 
		VL2_IIC_SCL=0;	
		delay_us(VL2_SPEED);
    }	 
} 

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 VL2_IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	VL2_SDA_IN();//SDA设置为输入
	for(i=0;i<8;i++ )
	{
		VL2_IIC_SCL=0; 
		delay_us(VL2_SPEED*2);
	  VL2_IIC_SCL=1;
		receive<<=1;
		if(VL2_READ_SDA)receive++;   
	  delay_us(VL2_SPEED*2); //1
	}					 
	if (!ack)
		VL2_IIC_NAck();//发送nACK
	else
		VL2_IIC_Ack(); //发送ACK   
	return receive;
}

//IIC写一个字节数据
u8 VL2_IIC_Write_1Byte(u8 SlaveAddress, u8 REG_Address, u8 data)
{
	VL2_IIC_Start();
	VL2_IIC_Send_Byte(SlaveAddress);
	if(VL2_IIC_Wait_Ack())
	{
		VL2_IIC_Stop();//释放总线
		return 1;//没应答则退出

	}
	VL2_IIC_Send_Byte(REG_Address);
	VL2_IIC_Wait_Ack();	
	VL2_IIC_Send_Byte(data);
	VL2_IIC_Wait_Ack();	
	VL2_IIC_Stop();

	return 0;
}

//IIC读一个字节数据
u8 VL2_IIC_Read_1Byte(u8 SlaveAddress, u8 REG_Address,u8 *REG_data)
{
	VL2_IIC_Start();
	VL2_IIC_Send_Byte(SlaveAddress);//发写命令
	if(VL2_IIC_Wait_Ack())
	{
		 VL2_IIC_Stop();//释放总线
		 return 1;//没应答则退出
	}		
	VL2_IIC_Send_Byte(REG_Address);
	VL2_IIC_Wait_Ack();
	VL2_IIC_Start(); 
	VL2_IIC_Send_Byte(SlaveAddress|0x01);//发读命令
	VL2_IIC_Wait_Ack();
	*REG_data = VL2_IIC_Read_Byte(0);
	VL2_IIC_Stop();

	return 0;
}

//IIC写n字节数据
u8 VL2_IIC_Write_nByte(u8 SlaveAddress, u8 REG_Address,u16 len, u8 *buf)
{
	VL2_IIC_Start();
	VL2_IIC_Send_Byte(SlaveAddress);//发写命令
	if(VL2_IIC_Wait_Ack()) 
	{
		VL2_IIC_Stop();//释放总线
		return 1;//没应答则退出
	}
	VL2_IIC_Send_Byte(REG_Address);
	VL2_IIC_Wait_Ack();
	while(len--)
	//while(*buf != '\0')
	{
		VL2_IIC_Send_Byte(*buf++);//发送buff的数据
		VL2_IIC_Wait_Ack();	
	}
	VL2_IIC_Stop();//释放总线

	return 0;
	
}

//IIC读n字节数据
u8 VL2_IIC_Read_nByte(u8 SlaveAddress, u8 REG_Address,u16 len,u8 *buf)
{
	VL2_IIC_Start();
	VL2_IIC_Send_Byte(SlaveAddress);//发写命令
	if(VL2_IIC_Wait_Ack()) 
	{
		VL2_IIC_Stop();//释放总线
		return 1;//没应答则退出
	}
	VL2_IIC_Send_Byte(REG_Address);
	VL2_IIC_Wait_Ack();

	VL2_IIC_Start();
	VL2_IIC_Send_Byte(SlaveAddress|0x01);//发读命令
	VL2_IIC_Wait_Ack();
	while(len)
	{
		if(len==1)
		{
			*buf = VL2_IIC_Read_Byte(0);
		}
		else
		{
			*buf = VL2_IIC_Read_Byte(1);
		}
		buf++;
		len--;
	}
	VL2_IIC_Stop();//释放总线

	return 0;
	
}

/**************************************以下是应用层调用的函数******************************************************/


//写多个数据
//address:地址
//index:偏移地址
//pdata:数据指针
//count:长度 最大65535
u8 I2C_SAND_BUFFER(u8 address, u8 index,u8 *pdata,u16 count)
{
	u8 status = STATUS_OK;

	if(VL2_IIC_Write_nByte(address,index,count,pdata))
	{
	   status  = STATUS_FAIL;

	}

	return status;
}


//读多个数据
//address:地址
//index:偏移地址
//pdata:数据指针
//count:长度 最大65535
u8 I2C_READ_BUFFER(u8 address,u8 index,u8 *pdata,u16 count)
{
	u8 status = STATUS_OK;

	if(VL2_IIC_Read_nByte(address,index,count,pdata))
	{
	  status  = STATUS_FAIL;
	}

	return status;
}

//写1个数据(单字节)
//address:地址
//index:偏移地址
//data:数据(8位)
u8 I2C_SAND_BYTE(u8 address,u8 index,u8 data)
{
	u8 status = STATUS_OK;

	status = I2C_SAND_BUFFER(address,index,&data,1);

	return status;
}

main.c

#include "stm32f10x.h" //STM32头文件
#include "sys.h"
#include "delay.h"
#include "o2adc.h"
#include "io_i2c.h" //在i2c文件夹中的i2c.c/h是硬件I2C总线驱动,io_i2c.c/h是模拟I2C总线驱动
#include "stdio.h"
#include "oled0561.h"

int main (void){//主程序
	u16 adcx1,adcx2;
	float temp1,temp2,o2c,o2f;
	u8 aa[5],bb[5];
	delay_ms(100); //上电时等待其他器件就绪
	RCC_Configuration(); //系统时钟初始化 

	I2C_Configuration();//I2C初始化

	OLED0561_Init(); //OLED初始化
	
	Adc_Init();
	
 
	
	while(1){
		adcx1=Get_Adc_Average(ADC_Channel_1 ,10);
		temp1=(float)adcx1*(3.3/4096);
		o2c = (temp1/3.3)*100;
		sprintf((char*)aa,"O2C:  %5.3f%%" ,o2c);
		OLED_DISPLAY_8x16_BUFFER(0,2,aa);
		
		adcx2=Get_Adc_Average(ADC_Channel_2 ,10);
		temp2=(float)adcx2*(3.3/4096);
		o2f = (temp2/3.3)*100;
		sprintf((char*)bb,"O2F:  %5.3f%%" ,o2f);
		OLED_DISPLAY_8x16_BUFFER(3,0,bb);
		
	}
}

  • 6
    点赞
  • 61
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32是一种微控制器系列,其具有高性能、低功耗和多种接口等特点。其主要用途是在嵌入式系统中进行控制和通信等任务。 OLED(Organic Light Emitting Diode),有机发光二极管显示技术,是一种新型的显示技术。与传统的LCD相比,OLED显示屏具有更高的对比度、更快的响应速度、更广的视角以及更低的功耗。 IIC(Inter-Integrated Circuit)是一种串行通信协议,被广泛应用于各种设备之间的通信。它具有简洁的线路结构、多设备连接、抗干扰能力强等优点。 当将STM32OLED结合使用时,可以通过IIC接口连接,实现显示功能。首先,需要在STM32上配置IIC接口,并将其与OLED连接。接下来,借助STM32的固件库或者驱动软件,可以通过IIC总线发送数据到OLED显示屏上。在STM32中,可以通过编写程序或使用相应的库函数,控制OLED显示内容、亮度、对比度等参数。 使用STM32OLED IIC显示有以下几个优点: 1. STM32具有强大的处理能力,能够处理更复杂的显示任务。 2. OLED显示屏具有高对比度和广视角,适用于各种环境。 3. IIC通信协议简单易用,可以有效减少线路复杂性。 4. STM32OLED显示屏的组合,可应用于各种嵌入式系统,如智能家居、移动设备等。 总结来说,STM32OLED IIC显示的组合能够提供一种高性能、低功耗、高质量的显示解决方案,适用于各种嵌入式系统应用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值