郑州艾特网站建设公司,互联网保险图片,移动互联网发展史,营销方式都有哪些基于FPGA控制PCF8591开展ADC采样 前言一、芯片手册阅读1.设备地址2.字节地址3.IIC通信协议 二、仿真分析三、代码分析总结视频演示 前言
这段时间做设计总是遇到一些传感器模块输出模拟电压#xff0c;采集模拟电压进而了解传感器输出的浓度占比#xff0c;在淘宝上找到了一… 基于FPGA控制PCF8591开展ADC采样 前言一、芯片手册阅读1.设备地址2.字节地址3.IIC通信协议 二、仿真分析三、代码分析总结视频演示 前言
这段时间做设计总是遇到一些传感器模块输出模拟电压采集模拟电压进而了解传感器输出的浓度占比在淘宝上找到了一个4通道的ADC采集模块用这个来获取不同传感器的模拟电压输出正好其实物如图所示 该模块具有ADC采样以及DAC输出的功能其中4路为ADC采样输入AIN0-4一路DAC输出AOUT。 与FPGA相连接的端口为VCC、GND、SCL、SDA主要就是通信协议的实现实现之前需要阅读芯片手册获取一下有用的关键信息通信速率从机设备地址、控制指令信息等等 产品参数 使用注意事项 供电5V你的adc输入范围就是0-5V如果用3.3V供电你的输入范围就是0-3.3V。不同的供电可能效果不同我目前遇到过好多供电问题然后换一种供电就工作正常所以大家遇到问题时要不断排除问题。 跳帽你如果需要用adc通道采集外部的模拟电压你就需要对应通道的跳帽拔下来。否则数据一直是模块本身自带的数据。
一、芯片手册阅读
1.设备地址
结合两个图发现还有A0-A2三个未知的比特通过查看模块原理图发现这三个引脚接地。所以设备地址确定为0x1001000 写数据就是0x90 读数据就是0x91
2.字节地址
一堆英文不想看看图就行了如下图所示每个比特干啥的都说的比较清楚。 从低位这边看[0:1]是负责说明对哪个通道进行操作的前面也提到了总共4个通道。 然后[2]这个比特默认为1 然后[3]默认为0 然后[4:5]说明这四个通道的输入模式有差分输入啥的不选择我只需要最普通的那种输入即可所以默认00 然后[6]在ADC时为0在DAC时为1 然后最高位默认为0
比如现在要对通道1进行ADC采样转化的功能实现就要发送0x00000000 比如现在要对通道2进行ADC采样转化的功能实现就要发送0x00000001 比如现在要对通道3进行ADC采样转化的功能实现就要发送0x00000010 比如现在要对通道4进行ADC采样转化的功能实现就要发送0x00000011
比如现在要对通道1进行DAC采样转化的功能实现就要发送0x01000000
3.IIC通信协议
了解一下基本的信息对后面实现通信流程有所参考。 如果发送完设备地址了后面采样转化可以进行连续操作。 数字量跟模拟量的关系
完整的通信流程应该就是如下图所示。
二、仿真分析
仿真测试文件忘了放哪里了。就是简单的iic驱动设备地址字节地址读取数据的命令都知道了就是按照时序进行发送就可以了。
三、代码分析
timescale 1ns/1ns// Author : EmbedFire
// Create Date : 2019/04/01
// Module Name : pcf8591_adda
// Project Name : ad
// Target Devices: Altera EP4CE10F17C8N
// Tool Versions : Quartus 13.0
// Description : AD电压测量模块
//
// Revision : V1.0
// Additional Comments:
// module pcf8591_ad
(input wire sys_clk , //输入系统时钟,50MHzinput wire sys_rst_n , //输入复位信号,低电平有效input wire i2c_end , //i2c设备一次读/写操作完成input wire [7:0] rd_data , //输出i2c设备读取数据output reg rd_en , //输入i2c设备读使能信号output reg i2c_start , //输入i2c设备触发信号output reg [15:0] byte_addr , //输入i2c设备字节地址output wire [15:0] adc_data1 , //adc1数据 output wire [15:0] adc_data2 //adc2数据
);//************************************************************************//
//******************** Parameter and Internal Signal *********************//
//************************************************************************//
//parameter define
parameter CTRL_DATA1 8b0100_0001; //AD/DA控制字
parameter CTRL_DATA2 8b0100_0010; //AD/DA控制字
parameter CNT_WAIT_MAX 18d6_9999 ; //采样间隔计数最大值
parameter IDLE 3b001,AD_START1 3b010,AD_CMD1 3b100,WAIT 3b101,AD_START2 3b110,AD_CMD2 3b111;//wire define
wire [31:0] data_reg1/* synthesis keep */; //数码管待显示数据缓存
wire [31:0] data_reg2/* synthesis keep */; //数码管待显示数据缓存
//reg define
reg [17:0] cnt_wait; //采样间隔计数器
reg [4:0] state ; //状态机状态变量
reg [7:0] ad_data1 ; //AD数据
reg [7:0] ad_data2 ; //AD数据wire [23:0] data_temp;
wire [23:0] data_temp1;wire [23:0] data_temp2;
wire [23:0] data_temp3;wire [23:0] po_data1 ;
wire [23:0] po_data2 ;
//********************************************************************//
//***************************** Main Code ****************************//
//********************************************************************//
//cnt_wait:采样间隔计数器
always(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n 1b0)cnt_wait 18d0;else if(state IDLE || state WAIT )if(cnt_wait CNT_WAIT_MAX)cnt_wait 18d0;elsecnt_wait cnt_wait 18d1;elsecnt_wait 18d0;//state:状态机状态变量
always(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n 1b0)beginstate IDLE;byte_addr 16b0;endelsecase(state)IDLE:beginbyte_addr 16b0;if(cnt_wait CNT_WAIT_MAX)state AD_START1;elsestate IDLE;endAD_START1:beginstate AD_CMD1;byte_addr CTRL_DATA1;endAD_CMD1:if(i2c_end 1b1)state WAIT;elsestate AD_CMD1;WAIT:beginif(cnt_wait CNT_WAIT_MAX)beginstate AD_START2;endelsestate WAIT;endAD_START2:beginstate AD_CMD2;byte_addr CTRL_DATA2;endAD_CMD2:beginif(i2c_end 1b1)state IDLE;elsestate AD_CMD2;enddefault:state IDLE;endcase//i2c_start:输入i2c设备触发信号
always(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n 1b0)i2c_start 1b0;else if(state AD_START1 || state AD_START2)i2c_start 1b1;elsei2c_start 1b0;//rd_en:输入i2c设备读使能信号
always(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n 1b0)rd_en 1b0;else if(state AD_CMD1 || state AD_CMD2)rd_en 1b1;elserd_en 1b0;byte_addr:输入i2c设备字节地址
//always(posedge sys_clk or negedge sys_rst_n)
// if(sys_rst_n 1b0)
// byte_addr 16b0;
// else
// byte_addr CTRL_DATA;//ad_data:AD数据
always(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n 1b0)ad_data1 8b0;else if((state AD_CMD1) (i2c_end 1b1)) //(state AD_CMD) (i2c_end 1b1))ad_data1 rd_data;always(posedge sys_clk or negedge sys_rst_n)if(sys_rst_n 1b0)ad_data2 8b0;else if((state AD_CMD2) (i2c_end 1b1)) //(state AD_CMD) (i2c_end 1b1))ad_data2 rd_data;//MQ-2:ppm pow(11.5428 * 35.904 * Vrl/(25.5-5.1* Vrl),1/0.6549);
//1/0.65491.53
// 11.5428 * 35.904 * Vrl/(25.5-5.1* Vrl)(414*vrl)/(25.5-5.1* Vrl)
//
//data_reg:数码管待显示数据缓存assign data_reg1 ((ad_data1 * 3300) 4d8);
assign data_reg2 ((ad_data2 * 3300) 4d8);assign data_temp (414*data_reg1);
assign data_temp1 25500-(5*data_reg1);
assign data_temp2 (414*data_reg2);
assign data_temp3 25500-(5*data_reg2);
//po_data:数码管待显示数据
assign po_data1 data_temp2/data_temp3;
//转换后的烟雾浓度0-150
assign po_data2 data_temp/data_temp1;assign adc_data1 po_data1[15:0];
assign adc_data2 po_data2[15:0];
endmodule
我这是采集两个通道的adc对控制字节进行了切换使用状态机。 逻辑分析仪读取的正常时序。 该说不说Quartus的逻辑分析仪使用感差于vivado。代码两个平台是通用的
总结
视频演示 FPGA环境监测火灾监测家居监测温湿度模块、烟雾模块、PM2.5模块等等蓝牙通信