新手想借用DeepSeek来免费编程,有点想多了。

新手想借用DeepSeek来免费编程,有点想多了。近几天 DeepSeek 很火 说 DeepSeek 未来将代替程序员的工作 今天试着让 DeepSeek 编了一段程序 先说结果吧 编的程序在 Keil 里通过不了 提示有好几处错误

大家好,欢迎来到IT知识分享网。

近几天DeepSeek很火,说DeepSeek未来将代替程序员的工作,今天试着让DeepSeek编了一段程序。

先说结果吧,编的程序在Keil里通过不了,提示有好几处错误。

个人认为,DeepSeek取代不了程序员的工作,最多只是一个工具,能提高程序员的工作效率,理由:

  1. 对于编程小白,出现的错误修改不了,把错误反馈给DeepSeek,又会出现新的错误,意味着就不能拿来就用,还是要找懂程序的人去改。
  2. DeepSeek强大在于它的推理过程,不管结果对不对,推理过程唬住了很多人。
新手想借用DeepSeek来免费编程,有点想多了。

以下是我提的需求:

用C语言写一段测试程序,如下: 要求:单片机使用STC89C52,ADC模块为ADS1256(精度为24位),有两路ADC同时输入(DC,0-5V)。 需求:ADC采样使用递推平均滤波算法,使用冒泡排序函数,去掉最高值、最低值,求中间平均值,将两路电压测试结果同时显示在LCD1602屏上。

已深度思考(用时 53 秒)

嗯,用户让我用C语言写一段测试程序,基于STC89C52单片机和ADS1256 ADC模块,同时采集两路0-5V的直流信号,并用递推平均滤波算法处理,还要用冒泡排序去掉最高和最低值,取中间平均值,最后显示在LCD1602上。首先,我得理清楚整个流程。

首先,STC89C52是8051内核的单片机,所以需要用Keil C之类的工具来编写。ADS1256是24位的高精度ADC,可能需要通过SPI接口来通信。我需要确认ADS1256的数据手册,了解其寄存器配置和通信协议。

接下来,两路ADC同时输入。ADS1256是否支持多通道同时采样?或者需要轮流切换通道?可能得看数据手册。假设这里需要交替读取两个通道的数据,或者使用某种多路复用方式。可能需要配置ADS1256的输入多路复用器,设置不同的通道,然后读取数据。

然后是递推平均滤波算法。用户提到使用递推平均,也就是滑动窗口平均,结合冒泡排序去掉最高和最低值。比如,每次采样保存最近的N个数据,排序后去掉头尾,取中间的平均值。需要确定窗口大小,比如10次采样,去掉最高和最低,取中间8次的平均。这样的话,需要为每个通道维护一个数组,保存最近的采样值。

冒泡排序函数需要实现,对数组进行排序,然后去掉第一个和最后一个元素,计算剩下的平均值。需要注意排序算法的正确性,以及处理数组索引的问题。

显示部分,LCD1602通常使用并行接口,需要定义正确的引脚连接,比如RS、RW、EN、数据线等。需要编写初始化LCD的函数,发送命令和数据的函数,以及显示字符串的函数。由于要同时显示两路电压,可能需要将两行显示分开,或者使用两行显示,比如第一行显示通道1,第二行显示通道2。

硬件连接方面,ADS1256的SPI接口需要连接到STC89C52的相应引脚,比如CLK、DIN、DOUT、CS等。可能还需要DRDY引脚来判断数据是否准备好。LCD1602的连接也需要确定,比如使用P0口作为数据线,其他控制引脚连接到P2口的几个脚。

在代码结构上,主程序可能需要初始化ADC、LCD,然后进入循环,不断读取两路ADC的数据,进行滤波处理,然后更新显示。需要注意的是,ADS1256的读取可能需要一定的时序,比如等待DRDY信号变低,然后发送读取命令,读取24位的数据,并进行补码转换,因为ADS1256的输出是二进制的补码形式。

另外,电压值的转换需要将24位的ADC值转换为0-5V的实际电压。24位的最大值是0x7FFFFF(正数)和0x(负数),但因为是0-5V输入,可能只使用单极性模式,所以实际输出是0到0x7FFFFF对应的0-5V。转换公式应该是电压 = (ADC值 / 0x7FFFFF) * 5V。但要注意处理数据的符号位,可能不需要,因为输入是0-5V,所以ADC值应该是正的。

可能的错误点:SPI通信时序是否正确,ADS1256的配置是否正确,数组索引处理是否正确,冒泡排序是否正确实现,电压转换计算是否正确,以及LCD显示格式是否正确。

需要分步骤实现:先配置ADS1256,测试能否正确读取单通道数据;然后实现滤波算法;接着添加第二通道;最后整合LCD显示。调试时可以用串口输出数据,确认ADC值是否正确,再处理显示部分。

另外,STC89C52的资源有限,RAM和ROM可能比较紧张,需要注意数组大小,避免溢出。例如,如果每个通道使用10个样本的数组,两个通道就是20个24位整数,可能占用较多内存,需要确认单片机的RAM是否足够。

可能还需要考虑ADC的采样率,以及程序的循环时间,确保能够及时读取和处理数据,不影响显示的刷新率。不过LCD1602的刷新不需要太快,所以可能问题不大。

总结,代码的大致结构包括:

1. 包含必要的头文件,如reg51.h,定义各引脚和宏。

2. 定义ADS1256相关的引脚和函数,如SPI读写、初始化配置、读取ADC数据。

3. 定义滤波算法相关的数组和函数,如冒泡排序、递推平均滤波。

4. 定义LCD1602的引脚和函数,初始化、写命令、写数据、显示字符串等。

5. 主函数中初始化各模块,进入循环,读取两路数据,滤波处理,显示结果。

需要注意的细节:ADS1256的初始化可能需要写入特定的寄存器配置,比如设置数据速率、增益、输入通道等。例如,设置通道1和通道2的多路复用,可能需要配置MUX寄存器。

另外,ADS1256的SPI通信可能需要特定的模式,比如CPOL和CPHA的设置,数据位顺序等,需要根据数据手册调整。

在代码中,可能需要使用位操作来控制引脚,例如CS引脚在通信开始时拉低,结束时拉高。

对于24位数据的读取,可能需要分三次读取高位、中位、低位字节,然后组合成一个有符号长整型,但根据输入范围,可能只需要处理无符号数。

最后,显示电压值时,可能需要将浮点数转换为字符串,但STC89C52不支持浮点运算,或者效率很低,可以考虑用整数运算代替,比如将电压值放大为毫伏,然后显示为整数和小数部分。

例如,电压值3.14V可以显示为3.14,通过将ADC值乘以5000,除以0x7FFFFF,得到毫伏值,然后格式化为字符串。

但处理浮点运算可能需要使用sprintf函数,或者手动分解各位数字。

或者,直接显示ADC的原始值进行调试,确认数据是否正确,之后再处理电压转换。

总之,这是一个涉及硬件接口、数据处理和显示的综合项目,需要逐步验证每个部分的功能,确保整体正确性。

以下是基于STC89C52和ADS1256的ADC采样及LCD显示程序示例:

#include <reg52.h> #include <intrins.h> / ADS1256 配置 / #define ADC_CLK P1_0 #define ADC_DOUT P1_1 #define ADC_DIN P1_2 #define ADC_CS P1_3 #define ADC_DRDY P1_4 / LCD1602 配置 / #define LCD_RS P2_0 #define LCD_RW P2_1 #define LCD_EN P2_2 #define LCD_DB P0 / 全局变量定义 / #define SAMPLE_SIZE 10 // 采样次数 #define FILTER_SIZE 8 // 有效样本数 unsigned long xdata adc_buf[2][SAMPLE_SIZE]; // 两路ADC数据缓存 unsigned char sample_cnt = 0; / 函数声明 / void DelayMS(unsigned int ms); void ADS1256_Init(); long ADS1256_ReadData(unsigned char channel); void BubbleSort(unsigned long arr[], unsigned char n); unsigned long FilterADC(unsigned char channel); void LCD_Init(); void LCD_WriteCmd(unsigned char cmd); void LCD_WriteData(unsigned char dat); void LCD_ShowStr(unsigned char x, unsigned char y, unsigned char *str); / 主函数 / void main() { unsigned char i; unsigned long voltage1, voltage2; unsigned char disp_buf[16]; LCD_Init(); ADS1256_Init(); LCD_ShowStr(0, 0, "CH1: 0.000V"); LCD_ShowStr(0, 1, "CH2: 0.000V"); while(1) { // 采集并滤波 adc_buf[0][sample_cnt] = ADS1256_ReadData(0); adc_buf[1][sample_cnt] = ADS1256_ReadData(1); sample_cnt = (sample_cnt + 1) % SAMPLE_SIZE; voltage1 = FilterADC(0); voltage2 = FilterADC(1); // 转换为电压值(假设参考电压5V) voltage1 = (voltage1 * 5000UL) / 0x7FFFFF; voltage2 = (voltage2 * 5000UL) / 0x7FFFFF; // 显示通道1 disp_buf[0] = 'C'; disp_buf[1] = 'H'; disp_buf[2] = '1'; disp_buf[3] = ':'; disp_buf[4] = ' '; disp_buf[5] = voltage1/1000 + '0'; disp_buf[6] = '.'; disp_buf[7] = (voltage1%1000)/100 + '0'; disp_buf[8] = (voltage1%100)/10 + '0'; disp_buf[9] = (voltage1%10) + '0'; disp_buf[10] = 'V'; disp_buf[11] = '\0'; LCD_ShowStr(0, 0, disp_buf); // 显示通道2 disp_buf[2] = '2'; // 修改通道号 disp_buf[5] = voltage2/1000 + '0'; disp_buf[7] = (voltage2%1000)/100 + '0'; disp_buf[8] = (voltage2%100)/10 + '0'; disp_buf[9] = (voltage2%10) + '0'; LCD_ShowStr(0, 1, disp_buf); DelayMS(200); } } / ADS1256 驱动函数 / void ADS1256_Init() { ADC_CS = 1; ADC_CLK = 0; // 添加具体初始化配置(根据ADS1256手册配置) } long ADS1256_ReadData(unsigned char channel) { unsigned char i; long result = 0; // 通道选择(根据ADS1256手册配置MUX寄存器) // ... while(ADC_DRDY); // 等待数据就绪 ADC_CS = 0; _nop_(); // 读取24位数据 for(i=0; i<3; i++) { result <<= 8; result |= SPI_ReadByte(); } ADC_CS = 1; // 处理符号位 if(result & 0x00) result |= 0xFF000000; return result; } / 滤波函数 / unsigned long FilterADC(unsigned char channel) { unsigned char i, j; unsigned long sum = 0; unsigned long temp[SAMPLE_SIZE]; // 复制数据到临时数组 for(i=0; i<SAMPLE_SIZE; i++) temp[i] = adc_buf[channel][i]; BubbleSort(temp, SAMPLE_SIZE); // 去掉首尾各1个值 for(i=1; i<SAMPLE_SIZE-1; i++) sum += temp[i]; return sum / (SAMPLE_SIZE-2); } / 冒泡排序 / void BubbleSort(unsigned long arr[], unsigned char n) { unsigned char i, j; unsigned long temp; for(i=0; i<n-1; i++) { for(j=0; j<n-1-i; j++) { if(arr[j] > arr[j+1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } } / LCD1602 驱动函数 / void LCD_Init() { LCD_WriteCmd(0x38); // 8位数据,双行显示 LCD_WriteCmd(0x0C); // 显示开,光标关 LCD_WriteCmd(0x06); // 地址递增,不移屏 LCD_WriteCmd(0x01); // 清屏 } void LCD_WriteCmd(unsigned char cmd) { LCD_RS = 0; LCD_RW = 0; LCD_DB = cmd; LCD_EN = 1; _nop_(); LCD_EN = 0; DelayMS(1); } void LCD_WriteData(unsigned char dat) { LCD_RS = 1; LCD_RW = 0; LCD_DB = dat; LCD_EN = 1; _nop_(); LCD_EN = 0; DelayMS(1); } void LCD_ShowStr(unsigned char x, unsigned char y, unsigned char *str) { if(y) x |= 0x40; x |= 0x80; LCD_WriteCmd(x); while(*str) { LCD_WriteData(*str++); } } / 延时函数 / void DelayMS(unsigned int ms) { unsigned int i, j; for(i=0; i<ms; i++) for(j=0; j<114; j++); }

说明:

  1. 需要根据实际硬件连接修改引脚定义
  2. ADS1256的SPI通信部分需要根据具体时序要求实现
  3. 电压转换部分假设ADS1256工作在单极性模式(0-5V)
  4. 显示部分使用整数运算避免浮点运算
  5. 滤波算法使用滑动窗口平均,去除最高和最低各1个值
  6. 需要根据实际需求调整采样次数和滤波参数

注意:

  • 需要参考ADS1256数据手册完成SPI通信和寄存器配置
  • LCD1602的显示位置需要根据实际需求调整
  • 可能需要添加电压校准功能以提高测量精度
  • 需要根据系统时钟调整延时函数参数

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/189814.html

(0)
上一篇 2025-10-07 08:26
下一篇 2025-10-07 08:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信