ADC串口控制(3)

// -----------------------------------------------------------------------------
// Copyright (c) 2014-2025 All rights reserved
// -----------------------------------------------------------------------------
// Author : lvjitao lvjitao_o@163.com
// File   : adc_ctrl_ads1256.v
// Create : 2025-10-18 09:06:14
// Revise : 2025-10-21 19:50:17
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
`timescale  1ns/1ps


module adc_ctrl_ads1256(
	//uart
	input	wire		clk,
	input	wire		rst_n,

	input	wire [7:0]	pi_data_rx,

	input	wire		pi_flag_rx,
	output	wire [7:0]	po_data_tx,
	output	wire		po_flag_tx,		

	//1256	spi	interface\
	input	wire		miso,

	output	wire		cs_n,
	output	reg		sclk,
	output	wire		mosi,

	//1256	ads1256 signal\
	input	wire		drdy,		//adctive low

	output	reg		reset,		//adctive low
	output 	wire		sync		//adctive low
	

    );

localparam	IDLE		=	10'b0000000001;
localparam	PREPARE_C	=	10'b0000000010;
localparam	WREG		=	10'b0000000100;
localparam	SYNC_S		=	10'b0000001000;
localparam	WAKEUP		=	10'b0000010000;
localparam	WAIT1		=	10'b0000100000;
localparam	RDATAC		=	10'b0001000000;
localparam	MISO_S		=	10'b0010000000;
localparam	WAIT2		=	10'b0100000000;
localparam	SDATAC		=	10'b1000000000;

localparam	RESET_MAX 	= 	500 - 1;
localparam 	CLK_CNT_MAX	= 	50 - 1;
localparam	STATE_CNT_MAX = 34;

localparam	SY_WA_RD_STATE_CNT_MAX = 18;

//cmd
localparam	CMD_WREG	=	24'h510078;
localparam	CMD_SYNC	=	8'hFC;
localparam	CMD_WAKEUP	=	8'hFF;
localparam	CMD_RDATAC	= 	8'h03;
localparam	CMD_SDATAC	=	8'h0F;

reg [9:0] 	state;
reg [1:0]	drdy_reg = 0;

reg [8:0]	reset_adc_cnt;

reg [5:0]	clk_cnt;
reg [5:0]	state_cnt;
reg [56:0]	shift_reg;

//delet
reg 		mosi_wreg;
reg 		mosi_sync;
reg 		mosi_wakeup;
reg 		mosi_rdatac;


assign cs_n = 1'b0;
assign sync = 1'b1;


always @(posedge clk ) begin
	if (rst_n == 1'b0) begin
		// reset
		reset_adc_cnt <= 'd0;
	end
	else if (reset_adc_cnt != RESET_MAX) begin
		reset_adc_cnt <= reset_adc_cnt + 1'b1;
	end
end

always @(posedge clk ) begin
	if (rst_n == 1'b0) begin
		// reset
		reset <= 1'b0;
	end
	else if (reset_adc_cnt == RESET_MAX) begin
		reset <= 1;
	end
end



always @(posedge clk ) begin
	if (rst_n == 1'b0) begin
		// reset
		state <= 'd0;
	end
	else case (state)
		IDLE: begin
			if (pi_flag_rx == 1'b1 && pi_data_rx == 8'hcc) begin
				state <= PREPARE_C;
			end
			else begin
				state <= IDLE;
			end
		end

		PREPARE_C: begin
			if (drdy_reg == 2'b10) begin
				state <= WREG;
			end
			else begin
				state <= PREPARE_C;
			end
		end

		WREG: begin
			if (state_cnt == STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
				state <= SYNC_S;
			end
		end

		SYNC_S: begin
			if (state_cnt == SY_WA_RD_STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
				state <= WAKEUP;
			end
		end

		WAKEUP: begin
			if (state_cnt == SY_WA_RD_STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
				state <= WAIT1;
			end
		end

		WAIT1: begin
			if (drdy_reg ==  2'b10) begin
				state <= RDATAC;
			end
		end

		RDATAC: begin
			if (state_cnt == SY_WA_RD_STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
				state <= MISO_S;
			end
		end


		default: state <= IDLE;

	endcase
end



always @(posedge clk ) begin
	drdy_reg <= {drdy_reg[0], drdy};
end

always @(posedge clk ) begin
	if (rst_n == 1'b0) begin
		// reset
		clk_cnt <= 0;
	end

	else if (state == WREG || state == SYNC_S || state == WAKEUP || state == RDATAC) begin
		if (clk_cnt == CLK_CNT_MAX) begin
			clk_cnt <= 0;
		end

		else begin
			clk_cnt <= clk_cnt + 1'b1;
		end
	end

end

always @(posedge clk ) begin
	if (rst_n == 'b0) begin
		// reset
		state_cnt <=  'd0;
	end
	else if (state == WREG ) begin
		if (state_cnt ==STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
			state_cnt <= 'd0;
		end
		else  if(clk_cnt == CLK_CNT_MAX)  begin
			state_cnt <= state_cnt + 1'd1;
		end
	end

	else if (state == SYNC_S || state == WAKEUP || state == RDATAC) begin
		if (state_cnt ==SY_WA_RD_STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
			state_cnt <= 'b0;
		end
		else  if(clk_cnt == CLK_CNT_MAX)  begin
			state_cnt <= state_cnt + 1'd1;
		end
	end

	else begin
		state_cnt <= 'b0;
	end
end

always @(posedge clk ) begin
	if (rst_n == 0) begin
		// reset
		sclk <= 0;
	end
	else if ((state == WREG && state_cnt <= 'd23) || ((state == SYNC_S || state == WAKEUP || state == RDATAC) && state_cnt <= 'd8)) begin
		 	if (clk_cnt == CLK_CNT_MAX[6:1]) begin
				sclk <= 1'b1;
			end
			else if (clk_cnt == CLK_CNT_MAX) begin
				sclk <= 1'b0;
			end
	end


	else begin
		sclk <= 0;
	end

end


always @(posedge clk ) begin
	if (rst_n == 0) begin
		// reset
		shift_reg <= {CMD_WREG, CMD_SYNC, CMD_WAKEUP, CMD_RDATAC, CMD_SDATAC};
	end
	else if (state ==IDLE) begin
		shift_reg <= {CMD_WREG, CMD_SYNC,CMD_WAKEUP, CMD_RDATAC, CMD_SDATAC};
	end
	else if ((state == WREG && state_cnt >= 1'd1 &&state_cnt <= 'd24) || ((state == SYNC_S || state == WAKEUP || state == RDATAC) && state_cnt >= 1'd1 &&state_cnt <= 'd8)) begin
		if (clk_cnt == CLK_CNT_MAX[6:1]) begin
			shift_reg <= {shift_reg[54:0], 1'b0 };
		end
	end
end




always @(*) begin
	if (state == WREG && state_cnt <= 'd23) begin
		// reset 
		mosi_wreg = shift_reg[55];
	end
	else begin
		mosi_wreg = 1'b0;
	end
end



always @(*) begin
	if (state == SYNC_S && state_cnt <= 'd8) begin
		// reset 
		mosi_sync = shift_reg[55];
	end
	else begin
		mosi_sync = 1'b0;
	end
end



always @(*) begin
	if (state == WAKEUP && state_cnt <= 'd8) begin
		// reset 
		mosi_wakeup = shift_reg[55];
	end
	else begin
		mosi_wakeup = 1'b0;
	end
end



always @(*) begin
	if (state == RDATAC && state_cnt <= 'd8) begin
		// reset 
		mosi_rdatac = shift_reg[55];
	end
	else begin
		mosi_rdatac = 1'b0;
	end
end


endmodule

// -----------------------------------------------------------------------------
// Copyright (c) 2014-2025 All rights reserved
// -----------------------------------------------------------------------------
// Author : lvjitao lvjitao_o@163.com
// File   : adc_ctrl_ads1256.v
// Create : 2025-10-18 09:06:14
// Revise : 2025-10-21 20:43:12
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
`timescale  1ns/1ps


module adc_ctrl_ads1256(
	//uart
	input	wire		clk,
	input	wire		rst_n,

	input	wire [7:0]	pi_data_rx,

	input	wire		pi_flag_rx,
	output	wire [7:0]	po_data_tx,
	output	wire		po_flag_tx,		

	//1256	spi	interface\
	input	wire		miso,

	output	wire		cs_n,
	output	reg		sclk,
	output	wire		mosi,

	//1256	ads1256 signal\
	input	wire		drdy,		//adctive low

	output	reg		reset,		//adctive low
	output 	wire		sync		//adctive low
	

    );

localparam	IDLE		=	10'b0000000001;
localparam	PREPARE_C	=	10'b0000000010;
localparam	WREG		=	10'b0000000100;
localparam	SYNC_S		=	10'b0000001000;
localparam	WAKEUP		=	10'b0000010000;
localparam	WAIT1		=	10'b0000100000;
localparam	RDATAC		=	10'b0001000000;
localparam	MISO_S		=	10'b0010000000;
localparam	WAIT2		=	10'b0100000000;
localparam	SDATAC		=	10'b1000000000;

localparam	RESET_MAX 	= 	500 - 1;
localparam 	CLK_CNT_MAX	= 	50 - 1;
localparam	STATE_CNT_MAX = 34;

localparam	SY_WA_RD_STATE_CNT_MAX = 18;

localparam	MISO_S_CNT_MAX 	=	24 - 1;

//cmd
localparam	CMD_WREG	=	24'h510078;
localparam	CMD_SYNC	=	8'hFC;
localparam	CMD_WAKEUP	=	8'hFF;
localparam	CMD_RDATAC	= 	8'h03;
localparam	CMD_SDATAC	=	8'h0F;

reg [9:0] 	state;
reg [1:0]	drdy_reg = 0;

reg [8:0]	reset_adc_cnt;

reg [5:0]	clk_cnt;
reg [5:0]	state_cnt;
reg [56:0]	shift_reg;

//delet
reg 		mosi_wreg;
reg 		mosi_sync;
reg 		mosi_wakeup;
reg 		mosi_rdatac;

reg [23:0]	mosi_data;
reg 		data_flag;




assign cs_n = 1'b0;
assign sync = 1'b1;


always @(posedge clk ) begin
	if (rst_n == 1'b0) begin
		// reset
		reset_adc_cnt <= 'd0;
	end
	else if (reset_adc_cnt != RESET_MAX) begin
		reset_adc_cnt <= reset_adc_cnt + 1'b1;
	end
end

always @(posedge clk ) begin
	if (rst_n == 1'b0) begin
		// reset
		reset <= 1'b0;
	end
	else if (reset_adc_cnt == RESET_MAX) begin
		reset <= 1;
	end
end



always @(posedge clk ) begin
	if (rst_n == 1'b0) begin
		// reset
		state <= 'd0;
	end
	else case (state)
		IDLE: begin
			if (pi_flag_rx == 1'b1 && pi_data_rx == 8'hcc) begin
				state <= PREPARE_C;
			end
			else begin
				state <= IDLE;
			end
		end

		PREPARE_C: begin
			if (drdy_reg == 2'b10) begin
				state <= WREG;
			end
			else begin
				state <= PREPARE_C;
			end
		end

		WREG: begin
			if (state_cnt == STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
				state <= SYNC_S;
			end
		end

		SYNC_S: begin
			if (state_cnt == SY_WA_RD_STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
				state <= WAKEUP;
			end
		end

		WAKEUP: begin
			if (state_cnt == SY_WA_RD_STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
				state <= WAIT1;
			end
		end

		WAIT1: begin
			if (drdy_reg ==  2'b10) begin
				state <= RDATAC;
			end
		end

		RDATAC: begin
			if (state_cnt == SY_WA_RD_STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
				state <= MISO_S;
			end
		end

		MISO_S:begin
			if (state_cnt == MISO_S_CNT_MAX || clk_cnt ==CLK_CNT_MAX) begin
				state <= WAIT2;
			end
		end

		WAIT2: begin
			if (drdy_reg == 2'b10) begin
				state <= MISO_S;
			end

		end



		default: state <= IDLE;

	endcase
end



always @(posedge clk ) begin
	drdy_reg <= {drdy_reg[0], drdy};
end

always @(posedge clk ) begin
	if (rst_n == 1'b0) begin
		// reset
		clk_cnt <= 0;
	end

	else if (state == WREG || state == SYNC_S || state == WAKEUP || state == RDATAC || state == MISO_S) begin
		if (clk_cnt == CLK_CNT_MAX) begin
			clk_cnt <= 0;
		end

		else begin
			clk_cnt <= clk_cnt + 1'b1;
		end
	end

end

always @(posedge clk ) begin
	if (rst_n == 'b0) begin
		// reset
		state_cnt <=  'd0;
	end
	else if (state == WREG ) begin
		if (state_cnt ==STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
			state_cnt <= 'd0;
		end
		else  if(clk_cnt == CLK_CNT_MAX)  begin
			state_cnt <= state_cnt + 1'd1;
		end
	end

	else if (state == SYNC_S || state == WAKEUP || state == RDATAC) begin
		if (state_cnt ==SY_WA_RD_STATE_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
			state_cnt <= 'b0;
		end
		else  if(clk_cnt == CLK_CNT_MAX)  begin
			state_cnt <= state_cnt + 1'd1;
		end
	end

	else if (state == MISO_S) begin
		if (state_cnt ==MISO_S_CNT_MAX && clk_cnt == CLK_CNT_MAX) begin
			state_cnt <= 'd0;
		end
		else  if(clk_cnt == CLK_CNT_MAX)  begin
			state_cnt <= state_cnt + 1'd1;
		end

	end

	else begin
		state_cnt <= 'b0;
	end
end



always @(posedge clk ) begin
	if (rst_n == 0) begin
		// reset
		sclk <= 0;
	end
	else if ((state == WREG && state_cnt <= 'd23) || ((state == SYNC_S || state == WAKEUP || state == RDATAC) && state_cnt <= 'd8) || state == MISO_S) begin
		 	if (clk_cnt == CLK_CNT_MAX[6:1]) begin
				sclk <= 1'b1;
			end
			else if (clk_cnt == CLK_CNT_MAX) begin
				sclk <= 1'b0;
			end
	end


	else begin
		sclk <= 0;
	end

end


always @(posedge clk ) begin
	if (rst_n == 0) begin
		// reset
		shift_reg <= {CMD_WREG, CMD_SYNC, CMD_WAKEUP, CMD_RDATAC, CMD_SDATAC};
	end
	else if (state ==IDLE) begin
		shift_reg <= {CMD_WREG, CMD_SYNC,CMD_WAKEUP, CMD_RDATAC, CMD_SDATAC};
	end
	else if ((state == WREG && state_cnt >= 1'd1 &&state_cnt <= 'd24) || ((state == SYNC_S || state == WAKEUP || state == RDATAC) && state_cnt >= 1'd1 &&state_cnt <= 'd8)) begin
		if (clk_cnt == CLK_CNT_MAX[6:1]) begin
			shift_reg <= {shift_reg[54:0], 1'b0 };
		end
	end
end



always @(posedge clk ) begin
	if (rst_n == 0) begin
		// reset
		mosi_data <= 0;
	end
	else if (state == MISO_S ) begin
		if (clk_cnt == CLK_CNT_MAX) begin
			mosi_data <= {mosi_data[22:0], miso};
		end
	end
end




always @(posedge clk) begin
	if (rst_n == 0) begin
		// reset
		data_flag <= 1'b0;
	end
	else if (state_cnt == MISO_S_CNT_MAX && state == MISO_S && clk_cnt == CLK_CNT_MAX) begin
		data_flag <= 1'b1;
	end
	else begin
		data_flag <= 0;
	end
end



always @(*) begin
	if (state == WREG && state_cnt <= 'd23) begin
		// reset 
		mosi_wreg = shift_reg[55];
	end
	else begin
		mosi_wreg = 1'b0;
	end
end



always @(*) begin
	if (state == SYNC_S && state_cnt <= 'd8) begin
		// reset 
		mosi_sync = shift_reg[55];
	end
	else begin
		mosi_sync = 1'b0;
	end
end



always @(*) begin
	if (state == WAKEUP && state_cnt <= 'd8) begin
		// reset 
		mosi_wakeup = shift_reg[55];
	end
	else begin
		mosi_wakeup = 1'b0;
	end
end



always @(*) begin
	if (state == RDATAC && state_cnt <= 'd8) begin
		// reset 
		mosi_rdatac = shift_reg[55];
	end
	else begin
		mosi_rdatac = 1'b0;
	end
end


endmodule
// -----------------------------------------------------------------------------
// Copyright (c) 2014-2025 All rights reserved
// -----------------------------------------------------------------------------
// Author : lvjitao lvjitao_o@163.com
// File   : tb_adc_ctrl_ads1256.v
// Create : 2025-10-18 16:17:48
// Revise : 2025-10-21 20:40:50
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
`timescale  1ns/1ps


module tb_adc_ctrl_ads1256(

    );

reg 		clk, rst_n;
reg 		pi_flag;
reg [7:0] 	pi_data;

wire 		sclk;
wire		cs_n, mosi, reset;
reg			drdy;

reg			miso;
reg [9:0]			tb_state;

wire 		state_match_flag;
reg [23:0]	adc_data;


assign state_match_flag = (tb_state == 10'h080) ? 1'b1 : 1'b0 ;

initial begin
	clk = 0;
	rst_n = 0;
	repeat(10) @(posedge clk);
	rst_n = 1;
end


always #10 clk = ~clk; 


initial begin
	drdy	= 0;
	pi_flag = 0;
	pi_data = 0;
	#10;
	@(posedge rst_n);
	repeat(10) @(posedge clk);
	pi_flag <= 1;
	pi_data <= 8'hcc;
	@(posedge clk);
	pi_flag <= 1'b0;

end


initial begin
	#10;
	gen_drdy();
end


initial begin
	adc_data = 0;
	miso = 0;
	force tb_state =  inst_adc_ctrl_ads1256.state;
	#10;
	gen_miso();

end

task gen_miso;
	integer i,j;
	begin
		for( j= 0; j<100; j=j+1) begin
			

			@(posedge state_match_flag) ;
			@(posedge sclk);
			miso = adc_data[23];
			for (int i = 0; i<23; i=i+1) begin
				@(posedge sclk);
				miso = adc_data[23 - i - 1];
			end
			adc_data = adc_data + 1'b1;

		end

	end


endtask

task gen_drdy;
	integer i;
	begin
		for(i=0; i<1000; i=i+1)begin
			drdy <= 0;
			#31000;
			drdy <= 1;
			#2333;


		end
	end


endtask



	adc_ctrl_ads1256 inst_adc_ctrl_ads1256(
			.clk        (clk),
			.rst_n      (rst_n),
			.pi_data_rx (pi_data),
			.pi_flag_rx (pi_flag),
			.po_data_tx (),
			.po_flag_tx (),
			.miso       (miso),
			.cs_n       (cs_n),
			.sclk       (sclk),
			.mosi       (mosi),
			.drdy       (drdy),
			.reset      (reset),
			.sync       (sync)
		);



endmodule

### 使用STM32通过串口控制ADC 在STM32微控制器中,可以通过串口发送命令来触发ADC转换并读取其结果。以下是具体实现方法以及示例代码。 #### 1. 初始化硬件资源 为了完成此功能,需要初始化以下几个模块: - **ADC模块**:用于采集模拟信号。 - **USART模块**:用于接收来自PC端的指令并将ADC采样结果显示到终端。 - **GPIO模块**:配置与ADC相连的通道引脚为模拟输入模式。 这些初始化操作可以基于HAL库或者标准外设库完成[^1]。 #### 2. 配置ADC参数 根据需求设置分辨率、扫描方向以及其他必要的选项。例如,在本项目中可能只需要单次转换模式下的某个特定通道的数据[^2]。 ```c // ADC Initialization Function static void MX_ADC_Init(void) { hadc.Instance = ADC1; hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4; // 设置时钟分频因子 hadc.Init.Resolution = ADC_RESOLUTION_12B; // 设定分辨率为12位 hadc.Init.ScanConvMode = DISABLE; // 关闭连续转换模式 hadc.Init.ContinuousConvMode = DISABLE; // 单一转换模式 hadc.Init.DiscontinuousConvMode = DISABLE; // 不启用不连续转换模式 hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;//无外部触发源 hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐 HAL_ADC_Init(&hadc); } ``` #### 3. 实现串口中断服务程序 当接收到指定字符(比如‘A’)时启动一次新的ADC转换过程,并把得到的结果打包成字符串形式再经由UART返回给主机计算机。 ```c void USART_IRQHandler(void){ uint8_t ReceivedData; if(HAL_UART_Receive_IT(&huart, &ReceivedData, 1)==HAL_OK){ if(ReceivedData==&#39;A&#39;){ /* Start the conversion */ HAL_ADC_Start(&hadc); while(HAL_ADC_PollForConversion(&hadc,10)!=HAL_OK); uint16_t result=HAL_ADC_GetValue(&hadc); char buffer[50]; sprintf(buffer,"The converted value is %d\r\n",result); HAL_UART_Transmit(&huart,(uint8_t*)buffer,strlen(buffer),1000); } } } ``` 以上片段展示了如何利用串行接口作为用户界面的一部分来进行交互式测量活动[^3]。 #### 完整流程说明 整个系统的运作逻辑大致如下所示: 1. 上电后进入等待状态; 2. 当检测到来自上层应用软件发出的有效请求帧之后立即响应执行相应动作——即开启一轮adc测试周期; 3. 测试结束后将最终量化后的离散数值反馈回去结束本次循环直至下一次查询再次激活为止;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值