AD7606与STM32F103ZET6的串行通信

AD7606与STM32F103ZET6的串行通信

  本文是AD7606与STM32的串行通信的学习心得,可帮助你快速入门AD7606。

时序图的理解

  图一
在这设定片描述
  图二
在这里插入图片描述
  图三
在这里插入图片描述
  图四
在这里插入图片描述
  根据图一,一些引脚在置高或置低时的上升或下降沿会受时间影响,因此在编写代码时,一些对引脚的操作需要放在一起,且延时函数不能随意使用。
  图二是整体的一个时序框图,大体的逻辑就是在使用AD7606之前要先复位一下,复位信号是高电平有效,时间至少为50ns。然后就是对采样速率和量程的配置,也就是对OS0,OS1,OS2和RANGE脚的配置,然后再对一些引脚进行一些初始化(也可以直接在GPIO配置的时候进行初始化)。之后就是发送启动信号,也就是将CVA,CVB同时拉低至少25ns后再拉高(启动信号上升沿有效)。之后AD7606开始转换,BUSY信号线自动拉高,如果BUSY信号线拉低则表明转换已经完成。转换完成后将CS片选信号线拉低才可以进行数据读取,读取完成后将CS片选信号线拉高即可。(还有一种是在转换时进行数据读取的,由于对于采样速率要求并不是特别的高,所以也没有深入研究)
  图三是串行通讯对数据进行读取的时序框图,讲的是在AD7606转换完成后将CS片选信号拉低后的操作。转换完成后CS片选信号拉低,开始读取数据。由于是16位8通道ADC,一次读取一个字节,所以一个通道需要读取两次数据。因为是高位在前低位在后所以就是先读取的是MSB,后读取的LSB,数据需要SCLK下降沿有效。经过16*8 = 128个SCLK读取后已经全部将ADC转换的数据全部读取完了,之后就可以将CS片选信号拉高了(由于串行通讯FRSTDATA数据线可以不接,所以并没有用到这个脚)。
  图四是对一个字节的读取,顺序也就是现将时钟线拉高后拉低然后读取一下当前的值然后拉高,重复八次就是一个字节的读取。(MSB的最高位为符号位,若为1则数据为负数,若为0则数据为正数)

计算公式的理解

在这里插入图片描述
  图上为计算公式,VIN为输入量,REF为ADC所选择的基准电压,一般使用内部基准电压REF=2.5V。上下两公式的选择,是由J2所接量程所决定。
  在程序中的计算公式:
在这里插入图片描述
  DB data[i]为AD所输出的二进制补码,可通过此方式计算出输入电压。

硬件电路连接

  串行工作方式:
在这里插入图片描述
  串行模式工作时,相关引脚连接方式:

rst 复位引脚
convstB 可以接在一起,当同时置低时 进行模拟量采样并处理
convstA
STby 控制工作模式,正常工作时一般直接接高电平
OS12 用于选择过采样倍率
OS11
OS10
busy 标志位,标志AD正在进行模拟量采样并处理
cs 片选信号,置低后标志可以开始输出模拟量
rd CS置低后的每一个上升沿输出每一位模拟量
DoutA(DB7) 数据输出线
D15 直接接地
SER 连接3.3 ,用于设定ADC为串行工作模式
5V
GND
RANGE J2用于选择输入电压的范围,影响计算公式
PB7 数据口,ADC最终通过此口给单片机发送数据

实物连接图

在这里插入图片描述

软件设计

  部分参数的定义

uint8_t read_flag=1;
s16	 DB_data[8]={0};
u8 i;
int32_t line=0;
int32_t reminder[32][32]={0};
uint8_t  temp;

  初始化函数

void AD7606_Init(void)
{
	convstA_Set;//同时拉高
	convstB_Set;
	delay_ms(1);
	STby_Set;//一直置高
	
	
	clk1_Set;//针对CLK和CS的操作尽可能地放在一起
	cs1_Set;	
	clk2_Set;//根据自己的需求连接几个CS和CLK 这里使用了四个ADC
	cs2_Set;
	clk3_Set;
	cs3_Set;
	clk4_Set;
	cs4_Set;
	
	
 	OS10_Reset;//过采样模式的初始化
	OS11_Reset;
	OS12_Reset;
	AD7606_reset();  
	delay_ms(1);
	AD7606_startconvst();	
}

  开始转化函数
  COA 与COB均是上升沿触发,因此需要同时拉低再拉高。

void AD7606_startconvst(void)
{  
	convstA_Reset;	
	convstB_Reset;	
	delay_us (1);
	convstA_Set;
	convstB_Set;
}

  复位函数
  REST是上升沿触发,因此先拉低再拉高再拉低。

void AD7606_reset(void) 
{ 
	rst_Reset;
	delay_us (1);
	rst_Set; 
	delay_us(1);
	rst_Reset; 
}  

  读数据函数,此处定义STM32的CO口与单片机的PB7数据线相连,读取AD转换的数据。

void  AD7606_read_data1(s16 * DB_data) 
{  
	u8 i,j; 	
	for(i=0;i<8;i++)  //循环8次是因为有8个通道
	{
		u16 DB_data1 = 0;//用于存储读出引脚的值
		cs1_Reset; //CS和CLK的引脚控制函数尽量放在一起
	  delay_us(1);	
		for(j=0;j<16;j++)//循环16次是因为寄存器可以存16位
		{		
		clk1_Reset;//CLK拉低开始输出
		delay_us(1);			
		DB_data1 = ((u16)(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0))<< (15-j)) + DB_data1 ;//AD输出为二级制补码,此处涉及部分寄存器的知识
	  	clk1_Set;
		delay_us(1);				
		}		
		cs1_Set;	
		DB_data[i] = (u16)DB_data1;//此处大致意思为将AD通道输出的值赋给一个存储内容为8的数组
	}	
	read_flag++;//多ADC使用时的标志位
} 

  遍历ADC函数
  注:1.此处的函数是使用一块STM32驱动四块AD7606,read_flag的使用是为了使相应的AD7606工作,如果你使用一块AD7606那么你看一个if里的函数就足够了。
  2.函数中包含的部分变量为全局变量,因此没有在函数的局部进行定义。

void throught_all(void)
{
		AD7606_startconvst();						
		temp = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5);	//判断BUSY线的反馈的值来决定对AD的操作
	  while(temp == 0)	
		{
			delay_us(1);
			temp = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_5);	
		}
	if(read_flag==1)
		{
			AD7606_read_data1(DB_data); //此函数返回一个数组,此数组的每一位中存放着相应通道采样的值,之后对该数组进行相应操作即可
								for(i=0;i<8;i++)
						{
							delay_us(100);
												line=2*i+1;/
												if(flag==0)
												{
												column=m+1;
												}
												if(flag==1)
												{
												column=m+17;
												}
										
													reminder[line-1][column-1]=(DB_data[i]*10000.0/32768);//计算公式的体现
						}	
			
		}
			if(read_flag==2)//以下为其他3个AD的操作程序
		{
			AD7606_read_data2(DB_data);
			
								for(i=0;i<8;i++)
						{
							delay_us(100);
											
												line=2*i+17;
												if(flag==0)
												{
												column=m+1;
												}
												if(flag==1)
												{
												column=m+17;
												}
										
													reminder[line-1][column-1]=(DB_data[i]*10000.0/32768);
											
						}
				
		}
	
			if(read_flag==3)
		{
			AD7606_read_data3(DB_data); 
			
								for(i=0;i<8;i++)
						{
							delay_us(100);
											
												line=2*i+2;
												if(flag==0)
												{
												column=m+1;
												}
												if(flag==1)
												{
												column=m+17;
												}
												
													reminder[line-1][column-1]=(DB_data[i]*10000.0/32768);
											
						}
							
		}
	
			if(read_flag==4)
		{
			AD7606_read_data4(DB_data); 
			
								for(i=0;i<8;i++)
						{

							delay_us(100);
											
												line=2*i+18;
												
												
												if(flag==0)
												{
												column=m+1;
												}
												if(flag==1)
												{
												column=m+17;
												}
											
												reminder[line-1][column-1]=(DB_data[i]*10000.0/32768);					
						}
								
		}
}

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇

)">
下一篇>>