实验原理
该实验主要为利用TLC549采集模拟信号,然后将模拟信号的数字量通过串口发送到PC上上位机进行显示,使用到的TLC549驱动模块在进阶实验已经使用到了,串口模块在基础实验也已经使用到了,本实验主要是做一个综合,将数据流进行一个整合。
硬件原理图
实验代码
顶层文件
TLC549驱动
/******************************************************************************* **----------------------------文件信息-------------------------- ** 文件名称:ADC_TLC549.v ** 功能描述:使用AD芯片TLC549采集模拟信号 ** 操作过程:将模拟信号接到TLC549的输入管脚上 *******************************************************************************/ module ADC_TLC549 ( clk,//系统50MHZ时钟 reset_n,//复位 ioclk,//AD TLC549的时钟 data,//AD TLC549的数据口 cs,//AD TLC549的片选择 segcs,//数码管的为选择 segdata,//数码管的7段码 send_finish,//发送完成标志 start,//开始采集信号 data_cnt,//数据位标志 voltage_data1,//采集的电压数据 voltage_data2,//采集的电压数据 voltage_data3,//采集的电压数据 voltage_data4 //采集的电压数据 ); input clk;//系统50MHZ时钟 input reset_n;//复位 input data;//AD TLC549的数据口 input send_finish;//发送完成标志 output cs;//AD TLC549的数据口 output ioclk;//AD TLC549的时钟 output start;//开始采集信号 output[7:0] voltage_data1;//采集的电压数据 output[7:0] voltage_data2;//采集的电压数据 output[7:0] voltage_data3;//采集的电压数据 output[7:0] voltage_data4;//采集的电压数据 output[3:0] data_cnt;//数据位标志 output[7:0]segdata; output[3:0]segcs; reg[7:0] voltage_data1;//采集的电压数据 reg[7:0] voltage_data2;//采集的电压数据 reg[7:0] voltage_data3;//采集的电压数据 reg[7:0] voltage_data4;//采集的电压数据 reg[3:0] data_cnt; // reg[7:0] voltage_data; reg[3:0] segcs; reg[7:0]segdata; reg start; reg cs,ioclk,clk1k,clk1ms; reg[15:0] count; reg[24:0] count1ms; reg[3:0] cnt; reg[2:0] number; reg[1:0] state; reg[7:0] dataout; reg[16:0] tenvalue; parameter sample=2'b00, display=2'b01; /**********产生100k的采集时钟信号*********/ always@(posedge clk) begin if(count<=250) count<=count+1'b1; else begin count<=0; ioclk<=~ioclk; end end /*******产生周期为1ms即1kHz的信号*********/ always@(posedge clk) begin if(count1ms>25'd25000) begin clk1ms<=~clk1ms; count1ms<=0; end else count1ms<=count1ms+1'b1; end /*********AD采样程序**************/ always@(negedge ioclk ornegedge reset_n) begin if(reset_n ==1'b0) begin start<=1'b0; state<=sample; cs<=1;//关AD片选 cnt<=0; tenvalue<=0; dataout<=0; end else begin case(state) sample: begin cs<=0; start<=1'b0; dataout[7:0]<={dataout[6:0],data}; if(cnt>4'd7) begin cnt<=0; state<=display; end else begin cnt<=cnt+1'b1; state<=sample; end end display: begin cs<=1;//关AD片选 tenvalue<=(tendata((dataout>>4)&8'b0000_1111)*16+ tendata(dataout &8'b0000_1111))*129;// //得到采集的数据 start<=1'b1; voltage_data1<=((tenvalue/10)%10)+8'd48;//个位 voltage_data2<=((tenvalue/100)%10)+8'd48;//十位 voltage_data3<=((tenvalue/1000)%10)+8'd48;//百位 voltage_data4<=(tenvalue/10000)+8'd48;//千位 if(send_finish ==1'b1) state<=sample; else state<=display; end default: state<=display; endcase end end /***********2进制转十进制函数*************/ function[7:0] tendata;//返回一个4位的数字 input[7:0] datain; begin case(datain) 4'b00000000: tendata=4'd0;//0 4'b00000001: tendata=4'd1;//1 4'b00000010: tendata=4'd2;//2 4'b00000011: tendata=4'd3;//3 4'b00000100: tendata=4'd4;//4 4'b00000101: tendata=4'd5;//5 4'b00000110: tendata=4'd6;//6 4'b00000111: tendata=4'd7;//7 4'b00001000: tendata=4'd8;//8 4'b00001001: tendata=4'd9;//9 4'b00001010: tendata=4'd10;// 4'b00001011: tendata=4'd11;// 4'b00001100: tendata=4'd12; 4'b00001101: tendata=4'd13; 4'b00001110: tendata=4'd14; 4'b00001111: tendata=4'd15; default:tendata=8'bzzzz_zzzz; endcase end endfunction /*********十进制转LED段选函数*********/ function[7:0] leddata;//返回一个8位的数字 input[3:0] datain; begin case(datain) 4'd0: leddata=8'b11000000;//0 4'd1: leddata=8'b11111001;//1 4'd2: leddata=8'b10100100;//2 4'd3: leddata=8'b10110000;//3 4'd4: leddata=8'b10011001;//4 4'd5: leddata=8'b10010010;//5 4'd6: leddata=8'b10000010;//6 4'd7: leddata=8'b11111000;//7 4'd8: leddata=8'b10000000;//8 4'd9: leddata=8'b10010000;//9 4'd10: leddata=8'b10111111;//- 4'd11: leddata=8'b01111111;//. default:leddata=8'bzzzz_zzzz; endcase end endfunction /********数码管扫描函数*************/ always@(posedge clk1ms) begin if(number==5) number<=0; else begin number<=number+1; case(number) 4'd0: begin segdata<=leddata((tenvalue/10)%10);//个位 segcs<=4'b1110; end 4'd1: begin segdata<=leddata((tenvalue/100)%10);//十位 segcs<=4'b1101; end 4'd2: begin segdata<=leddata((tenvalue/1000)%10);//百位 segcs<=4'b1011; end 4'd3: begin segdata<=leddata(tenvalue/10000);//千位 segcs<=4'b0111; end 4'd4: begin segdata<=leddata(4'd11);//. 显示小数点 segcs<=4'b0111; end endcase end end endmodule |
UART通信
/******************************************************************************* ** 文件名称:uart.v ** 功能描述:串口通信__FPGA和上位机通信(波特率:9600bps,10个bit是1位起始位,8个数据位,1个结束) *******************************************************************************/ module uart( clk, rst, rxd, txd, start, data_cnt, voltage_data1, voltage_data2, voltage_data3, voltage_data4, send_finish ); input clk;//系统50MHZ时钟 input rst;//复位 input rxd;//串行数据接收端 output txd;//串行数据发送端 input start;//开始采集信号 input[3:0] data_cnt;//数据位标志 input[7:0] voltage_data1;//采集的电压数据 input[7:0] voltage_data2;//采集的电压数据 input[7:0] voltage_data3;//采集的电压数据 input[7:0] voltage_data4;//采集的电压数据 output send_finish;//发送完成标志 reg[15:0] div_reg;//分频计数器,分频值由波特率决定。分频后得到频率8倍波特率的时钟 reg[2:0] div8_tras_reg;//该寄存器的计数值对应发送时当前位于的时隙数 reg[3:0] state_tras;//发送状态寄存器 reg clkbaud_tras;//以波特率为频率的发送使能信号 reg clkbaud8x;//以8倍波特率为频率的时钟,它的作用是将发送或接受一个bit的时钟周期分为8个时隙 reg trasstart;//开始发送标志 reg send_finish; reg txd_reg;//发送寄存器 reg[7:0] rxd_buf;//接受数据缓存 reg[7:0] txd_buf;//发送数据缓存 reg[3:0] send_state;//发送状态寄存器 parameter div_par=16'h145; //分频参数,其值由对应的波特率计算而得,按此参数分频的时钟频率是波倍特率的8 //倍,此处值对应9600的波特率,即分频出的时钟频率是9600*8 (CLK50M) assign txd = txd_reg; // assign send_state=data_cnt; /*******分频得到8倍波特率的时钟*********/ always@(posedge clk ) begin if(!rst) div_reg<=0; elsebegin if(div_reg==div_par-1'b1) div_reg<=0; else div_reg<=div_reg+1'b1; end end always@(posedge clk) begin if(!rst) clkbaud8x<=0; elseif(div_reg==div_par-1'b1) clkbaud8x<=~clkbaud8x;//分频得到8倍波特率的时钟:clkbaud8x end // *******************************/ always@(posedge clkbaud8x ornegedge rst)//clkbaud8x begin if(!rst) div8_tras_reg<=0; elseif(trasstart) div8_tras_reg<=div8_tras_reg+1'b1;//发送开始后,时隙数在8倍波特率的时钟下加1循环 end always@(div8_tras_reg) begin if(div8_tras_reg==7) clkbaud_tras=1;//在第7个时隙,发送使能信号有效,将数据发出 else clkbaud_tras=0; end // *********发送数据模块***************/ always@(posedge clkbaud8x ornegedge rst)//clkbaud8x begin if(!rst) begin txd_reg<=1;//发送寄存器置高 trasstart<=0;//开始发送标志置低 txd_buf<=8'h00;//发送缓存器清零 state_tras<=0;//发送状态寄存器清零 send_finish <=1'b0; send_state<=4'd0; end else if(start ==1'b1) case(state_tras) 4'b0000:begin//发送起始位 send_finish <=1'b0; if(!trasstart&&send_state<4'd7) trasstart<=1; elseif(send_state<4'd7)begin if(clkbaud_tras)begin txd_reg<=0; state_tras<=state_tras+1'b1; end end elsebegin state_tras<=0; end end 4'b0001:begin//发送第1位 if(clkbaud_tras)begin txd_reg<=txd_buf[0]; txd_buf[6:0]<=txd_buf[7:1]; state_tras<=state_tras+1'b1; end end 4'b0010:begin//发送第2位 if(clkbaud_tras)begin txd_reg<=txd_buf[0]; txd_buf[6:0]<=txd_buf[7:1]; state_tras<=state_tras+1'b1; end end 4'b0011:begin//发送第3位 if(clkbaud_tras)begin txd_reg<=txd_buf[0]; txd_buf[6:0]<=txd_buf[7:1]; state_tras<=state_tras+1'b1; end end 4'b0100:begin//发送第4位 if(clkbaud_tras)begin txd_reg<=txd_buf[0]; txd_buf[6:0]<=txd_buf[7:1]; state_tras<=state_tras+1'b1; end end 4'b0101:begin//发送第5位 if(clkbaud_tras)begin txd_reg<=txd_buf[0]; txd_buf[6:0]<=txd_buf[7:1]; state_tras<=state_tras+1'b1; end end 4'b0110:begin//发送第6位 if(clkbaud_tras)begin txd_reg<=txd_buf[0]; txd_buf[6:0]<=txd_buf[7:1]; state_tras<=state_tras+1'b1; end end 4'b0111:begin//发送第7位 if(clkbaud_tras)begin txd_reg<=txd_buf[0]; txd_buf[6:0]<=txd_buf[7:1]; state_tras<=state_tras+1'b1; end end 4'b1000:begin//发送第8位 if(clkbaud_tras)begin txd_reg<=txd_buf[0]; txd_buf[6:0]<=txd_buf[7:1]; state_tras<=state_tras+1'b1; end end 4'b1001:begin//发送停止位 if(clkbaud_tras)begin txd_reg<=1; txd_buf<=8'h00; state_tras<=state_tras+1'b1; end end 4'b1111:begin if(clkbaud_tras)begin state_tras<=state_tras+1'b1; send_state<=send_state+1'b1; trasstart<=0; case(send_state) 4'b0000: txd_buf<=voltage_data4;//个位 4'b0001: txd_buf<=8'd46;//小数点 4'b0010: txd_buf<=voltage_data3;//十位 4'b0011: txd_buf<=voltage_data2;//百位 4'b0100: txd_buf<=voltage_data1;//千位 4'b0101: txd_buf<=8'd86;//"V" 4'b0110: begin txd_buf<=8'd10;//换行符 send_finish <=1'b1; send_state<=4'b0000; end default: txd_buf<=8'd0; endcase end end default:begin if(clkbaud_tras)begin state_tras<=state_tras+1'b1; trasstart<=1; end end endcase end endmodule |
大西瓜FPGA-->https://daxiguafpga.taobao.com
博客资料、代码、图片、文字等属大西瓜FPGA所有,切勿用于商业! 若引用资料、代码、图片、文字等等请注明出处,谢谢!
每日推送不同科技解读,原创深耕解读当下科技,敬请关注微信公众号“科乎”。