欢迎大家来到IT世界,在知识的湖畔探索吧!
500A功率采集电路原理和源码分析
最大电流采样500A,主要应用在电力上的对某个电网进行瞬时功率,平均功率,总功率采集
通过STM32微控制器,对电网信号进行采样处理
设计参数
(1) 电压参数 0-105V
(2)电流参数 0-500mA,0-5A,0-500A
(3) 最大频率成分 <25kHz
(4) AD采样率600kHz(方便处理),功率采样率300kHz
结果输出:每秒通过串口将p、P、W发送到PC端
这是整体电路
欢迎大家来到IT世界,在知识的湖畔探索吧!
我们主要分析电流采样这块
电流采样这块采用精密零漂移电流检测放大器U3 LTC6102,VIN输入最高为105V(电网的电压经过变压器整流降压的),通过外部检测电阻RoutX和RoutX_ADJ (分流 电阻) 两端的电压来监测电流(0-500ma,0-5A,0-500A)。内部电路将输入 电压转换为输出电流,使得大共模电压上的小检 测信号可以转换为以地为基准的信号。低直流失 调电压支持使用非常小的分流电阻值和较大的 增益设置电阻。电流精度可以达到10ma,电流采样电阻采用大功率Rsense 1mR,最大检测电流达到电网的500A。下图最右边是对电流采样原理和计算公式。
对电流采样采用二阶低通滤波器,这个是一个有源滤波器,用工作在线性区的集成运放和 RC 网络组称,实际上是一种具有特定频 率响应的放大器,主要滤除电网负载的波动
具体原理如下:
U3的输出经过PR2、CC2、PR1、CC1构成二阶低通滤波电路,R1、Rf1、Rf1_ADJ构成同相比例放大电路,Rf1_ADJ可以调节电路的放大倍数,这是计算公式
在集成运放U2输出到集成运放同相输入之间并联电容CC2引入一个负反馈,主要作用是,在不同的频段,反馈的极性不相同,当信号频率f>>f0时(f0 为截止频率),电路的每级RC 电路的相移趋于-90º,两级RC 电路的移相到-180º,电路的输出电压Vout与输入电压Vin的相位相反,故此时通过电容CC2引到集成运放同相端的反馈是负反馈,反馈信号将起着削弱输入信号的作用,使电压放大倍数减小,所以该反馈将使二阶有源低通滤波器的幅频特性高频端迅速衰减,只允许低频端信号通过。其特点是输入阻抗高,输出阻抗低。
下图是低通滤波器的频率特性曲线
我们对电流采样的同时也对电网负载的电压进行实时采集,就是说电压和电流是同步采集。
具体原理如下
电网负载电压LOAD_VCC经过电阻VR2、VR1、VR1_ADJ分压,把电网的高电压变成低电压给运放U4滤波采集,和上面的电流采样原理一样
下图是电压采样频率特性图
最后是功率数据处理
我们采用DMA采样并传输数据
通过调整缓冲区大小,可调整DMA中断周期
具体的功率计算如下
瞬时功率
平均功率
总功率
源码分析,ADC初始化
void ADC1_Mode_Config(void) { DMA_InitTypeDef DMA_InitStructure; ADC_InitTypeDef ADC_InitStructure; //DMA1 通道1 /* DMA1 channel1 configuration */ DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; DMA_InitStructure.DMA_MemoryBaseAddr = (u32)ADC_VAL;// DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;//从外设读取数据 DMA_InitStructure.DMA_BufferSize = (CHANNEL*BUFFER_SIZE);//3KB (HW) DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//DMA地址增加 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;//16bit DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;//16bit DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); DMA_ClearITPendingBit(DMA1_IT_TC1); DMA_ITConfig(DMA1_Channel1,DMA1_IT_TC1,ENABLE);//DMA1传输完成中断 /* Enable DMA channel1 */ DMA_Cmd(DMA1_Channel1, ENABLE); /* ADC1 configuration */ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//ADC独立转换模式,相对于双重模式 ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描模式 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//连续转换模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 2; ADC_Init(ADC1, &ADC_InitStructure); // ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_28Cycles5); // ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_28Cycles5); /* ADC1 regular channel configuration */ //AD采样率为12000K/(7.5+12.5)=600K ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_7Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_7Cycles5); /* Enable ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /* Enable ADC1 reset calibaration register */ ADC_ResetCalibration(ADC1); /* Check the end of ADC1 reset calibration register */ while(ADC_GetResetCalibrationStatus(ADC1)); /* Start ADC1 calibaration */ ADC_StartCalibration(ADC1); /* Check the end of ADC1 calibration */ while(ADC_GetCalibrationStatus(ADC1)); }
欢迎大家来到IT世界,在知识的湖畔探索吧!
……
原文链接:https://www.dianyuan.com/eestar/article-1632.html
开源之RFID自动分拣系统
自动化物流系统可以对库存的入库、出库、移库、盘点等操作进行全面的控制和管理,对物品进行实时分析与控制,为企业管理者作出正确决策提供依据,将库存量减至最优存储量,大幅提高资金流转速度与利用率,降低库存成本;从物流效率和管理水平、空间利用率、人工成本、等方面可以看出,自动化物流系统与传统物流系统相比,具有更加明显的优势。
今天简单分享一下物流自动化仓储分拣系统的自动识别原理,下面是基本的原理图:
具体工作原理如下:
主控MCU采用stm32F103C8T6,是目前非常常用的一个单片机型号,采用M3内核,72M主频,采用射频模块主要是用来获取RFID标签中的数据信息,当系统处于主菜单时,按下键盘中的OK键,启动射频模块(拉低SHD引脚)。单片机通过捕获EM4095的DEMOD_OUT引脚输出的曼切斯特码波形,利用解码算法获取当前读入标签的信息。如果读取到标签的信息,则在屏幕上显示标签ID号;并通过单片机TTL串口将数据通过wifi模块发送给服务器
一、一键启动电路
图中KEY_COND和EN_A分别与单片机的IO口相连。其工作原理为:
- 当系统处于关闭时,EN_A通过R26处于低电平,SP6205稳压器不工作,此时系统没有上电。当按下电源键(KEY_POWER),EN_A为高电平,系统启动。又由于EN_A与IO脚相连,启动后立即将EN_A拉高,这时抬起电源按键,实现自锁,系统正常工作。
- 当系统处于运行状态时(电源键没有按下),此时EN_A为高电平,但由于分压电阻R24,R25的存在,KEY_COND上的电压只有50mV可以认为是低电平,当按下电源按键,此时KEY_COND拉高并能被单片机读取,当抬起电源按键后KL25将与EN_A相连的IO脚电平拉低,这时SP6205停止工作,系统关闭。
二、射频模块识别原理
射频模块这块是采用识别近距离RFID标签并为节省能源降低功耗,因此选用低频段RFID技术,选用EM5095芯片作为射频模块的主芯片。EM4095是EM MICROELECTRONIC公司开发的一款CMOS集成的应用于100kHz~150kHz频率的RFID系统的收发前端芯片,其工作电压为5V,主要完成的工作是:
EM4095与单片机连接的信号有三个引脚,用于数据和时钟的传输以及系统对EM4095的驱动和控制:
- DEMOD_OUT:输出信号,为EM4095感应到线圈上的AM信号后经过解调后得到的曼彻斯特编码信号,将之接收并解码校验后可得到所读出的标签的值。
- RDY/CLK:时钟信号,为EM4095从天线线圈上提取出的经过谐振后的时钟频率,范围应在100kHz-150kHz,而本文所设计的系统此频率在125kHz。
- SHD:休眠控制信号,此引脚为高电平时,EM4095将被强制进入休眠状态,天线线圈上没有电流,目的是保护芯片和节省能源。
- EM4095与单片机的连接方式并不是标准的控制和通信接口,无法利用单片机任何现成的控制和接口单元对其进行驱动和控制,根据EM4095的DEMOD_OUT,RDY/CLK和SHD这三个引脚,并按其数据手册上工作原理进行控制。
- DEMOD_OUT为EM4095感应到线圈上的AM信号后经过解调后得到的曼彻斯特编码信号,因此将与DEMOD_OUT引脚连接的单片机的IO设置为输入,将曼彻斯特编码信号读入到单片机中。
- RDY/CLK为EM4095的时钟信号,主要是在系统启动时,检测EM4095芯片能否正常工作。
- SHD引脚控制的内容为EM4095的线圈加电,在不需读取RFID标签信息时将SHD引脚拉高,线圈未上电,EM4095不工作;在需要读取RFID标签信息时将SHD引脚拉低,EM4095正常工作
三、源码分析
检测方法1).确定起始位,首先要正确找到数据1 按规则下跳为1 上跳为0. 可检测高电平并等其变低 但这会把0错检为1因为0也存在高电平。但是如果检测到一个周期的高电平(数据01)则可 确定找到了数据1,找到1后就可以同步了,因为EM4100卡最后一位数据就是0正好可以利用 作为判断的特征。
2).对于数据的确定,由于有了同步则可在同步后延时384us即3/4个码原周期在判断接受段电平如何 如为高则置数据为1,并一直等到低电平的出现,相反则等高电平的出现,并在此之间插入超时 判断。这样,一个完整的数据判断就完成了,并确保数据的准确性,另外这种方法的抗干扰性 会非常好,而如果采用定时同步的话则会因信号的畸变而引起数据出错,整体会导致读卡几率降低 但是此程序也有其缺点,因为采用纯延时判断的手段,因此其占用单片机的运行时间比较大。
3).同步后开始接受同步数据即9个1,这一部分用一个循环做,如果出错则放弃接收
4).同步数据接收完后,则开始接受数据,数据分11行5列接收以利于校验位的判断 如有出错则放弃数据
5).如一切正常则返回卡号,如因尝试读卡次数到了则返回0以表示没有识别到标签……
原文链接:https://www.dianyuan.com/eestar/article-1669.html
实例分析stm32F103逆变器(源码+硬件)
正值国产替代进行时,目前国内主流的两大MCUx之GD32,MM32,基本上都可以替代ST的103系列,但是都需要一个过程,这次还是以stmF103系列的单片机为主,分享逆变器整个硬件和软件。
我们平时用的最多的是DCDC,ACDC,而DC to AC原理就不言而喻了,逆变电源就是相对于整流器而言通过半导体功率开关器件的开通和关断把直流电变换成交流电的这么一 个装置,逆变电源也叫做逆变器,这次是12V电池供电,输出正弦波。下面分单元地讲一下逆变器主要的单元电路。
一.电池输入电路
逆变器大多用在车载上,利用汽车上的蓄电池和发电机组成的低压直流供电系统供电。这个系统上往往还给其他的用电器供电,所以有必要在逆变器的输入端设计一个输入电路保证能滤除大部分来自直流供电系统的纹波和干扰,同时也滤除逆变器对直流供电系统上其他用电器的干扰。输入电路一般由 LC 构成,输入电路设计中需要注意的是 L 要能过足够的电流不会饱和和过热。LC 的参数还要能起到滤波效果。在实际的电路中也往往在节省成本或要求不高时省去 L.
二.辅助电源电路。
逆变器除了功率变换回路外,还包含了小信号部分的供电,例如 PWM 信号芯片的
12V 供电,运放的单电源或双电源供电,单片机的 5V 或 3.3V 供电等。对上述电路提供一个稳定的纯净的电源供电在逆变器中也显得很重要。
12V 电池输入的辅助电源电路
对于 12V 电池供电的逆变器,一般经过一级 RC 滤波给 PWM 芯片如 TL494,SG3525 等供电即可。需要注意的是 R 的压降控制在 0.5V-1V 比较合适,因为一般 PWM 芯片最低工作电压在 8V 左右,为了使电池在 10V 电压时还能工作,R 上的压降不能过大。还有 PWM 芯片供电电压过低容易引起不工作或对功率 MOS 管驱动不足。
在要求比较高的情况下可以先把 10-15V 的电池电压升压到 15V,再用 L7812 降压到稳定的 12V 给 PWM 芯片供电,电路如下:
上图中 BT 为来自 12V 电池,电压变动范围为 10-15V.采用了 MC34063 单片 DCDC 芯片比较简单经济地实现了上述功能。
2.24V-48V 电池输入的辅助电源电路
在输入 24V 以上的逆变器中,要是用 L7812,LM317 之类的线性降压会造成比较大的发热损耗,因此本人设计了一个自激开关式降压电路,现在介绍给大家:
在这个电路中,BT 输入电压范围可以达到 15-60V,而输出稳定在 12V.Q6 也可以用 P型的 MOS 管。
下面来讲一下这个电路的工作原理,电路起动的瞬间,电源通过 R13 提供 Q6 足够大的基极电流,Q6 饱和导通,其集电极电流一部分通过 L1 给 C15 充电供给负载,一部分储存在 L1 里。当 C15 两端的电压超过 15V 时 Q7 导通,Q5 也导通导致 Q6 的基极电位上升,电流减小,C11 的上端的电位下降,由于 C11 两端的电压不能突变,Q5 基极的电位继续迅速下降,Q6 的基极电位迅速上升直到快速关断,Q6 关断后 L1 的储能通过续流二极管 D2 释放给 C15 和负载,然后开始下一个周期的循环。
3.多路隔离辅助电源电路
对于需要一路或多路隔离辅助电源供电的时候,一般采用反激式开关电源供电比较好实现,如下图,这里就不详细介绍了。
三.高频逆变器前级电路的设计
逆变器前级电路一般采用推挽结构,这里主要讲解下开环和闭环的问题。供分析的电路如下:
闭环前级变压器匝数比的设计
逆变器前级无论是开环还是闭环只是变压器的匝比和反馈环路的参数不同而已。比如需要设计一个输入 12V,变化范围为 10.5-15V,输出电压为交流 220V50Hz 的高频修正方波逆变器。如果前级采用闭环结构,12V 升压后的直流电压稳定在 270V 比较好,这样为了使输入
10.5V 时还能输输出 270V,则变压器的变比大约为(270+2VD)/(10.5-VDS)/D,其中 VD 为高压整流管的压降,VDS 为前级 MOS 管的压降,D 为最大占空比。计算出来的结果大约是 28。特别注意的是当前级工作在闭环状态时,比如输入电压比较高的话,D1,D3 正端整流出来的脉冲的峰值将超过 270V,占空比小于 1 需要 L1,C11 平滑滤波,所以 L1 不能省略,还要足够大,否则 MOS 管发热损耗很大。具体计算可根据正激类开关电源输出滤波电感的计算,这里就不再赘述了……
原文链接:https://www.dianyuan.com/eestar/article-1693.html
实例分析stm32控制的智能手环(源码+硬件)
智能手环现在再普通不过了,大家跑步和睡觉时可能会带上,今天简单分享一下stm32控制的智能手环
下面是基本的原理图
原理框架图
一、原理介绍
如上图所示,触摸屏采用的是2.0寸的全视角IPS TFT彩屏 采用8位数据口控制,大大减少IO的使用,驱动采用的ILI9335,更加容易地移植STemWin,触摸板是自己加上的,触摸IC为XTP2046,采用模拟SPI采集触摸屏AD值。震动电机采用普通IO口控制,当有电话来或者接到短信的时候就打开,直到电话接起或者拒接。利用MCU自带的ADC对心率传感器的电压进行采集,通过MCU处理后,利用STemWin的GRAPH控件构建心率图。
串口6连接蓝牙模块对智能开关进行控制,控制风扇、电灯等,并利用蓝牙模块进行温度无线采集。用户按键的主要功能是锁、开屏和开、关机(进入停机模式),则按键用WKUP功能引脚。SIM908通信模块带有GSM、GPRS和GPS功能,是此智能手表功能实现的主要核心,智能手表的通话、短信、远程追踪功能都是由此模块来实现。SD卡模块用来保存中文字库和收到的短信。为了提高安全性,采用管理员管理模式,当检测到管理员发来的短信命令时,才允许手表打开其追踪功能,管理员的账号密码保存在AT24c02这一非易失性存储IC中。
此为SIM908原理图,包含SIM卡及四段式耳机等,SIM908对静电相当敏感,所以加入ESD防止静电干扰。
采用STemWin图像用户界面,实现窗口化管理,在手表的状态栏显示通信运营商的信息和信号大小,利用sim908自带ADC采集电池电量信息,并在状态栏显示。在主窗口显示时间,用ICONVIEW小工具构建成手表的应用。一共有六个应用。
手环说明:
按键设置在手表底部,用于锁屏用,底部还有个四段式耳机接口,用于通话功能!
手表顶部有个震动电机,来电的时候震动起来真心带感,USB接口用于充电用。
手表的侧面有两个充电状态指示灯,分别提示正在充电和已经充满。另外一侧则是电源开关和心率传感器接口。
二、程序这块简单分析
这是主函数
欢迎大家来到IT世界,在知识的湖畔探索吧!void USART1_IRQHandler(void) { char data; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { // USART_ClearFlag(USART1,USART_IT_RXNE); data = USART_ReceiveData(USART1); if(GSM_RX_FLAG < DATA_BUFF_SIZE) //还能接收数据 { TIM3->CNT = 0; //清空计数器 if( GSM_RX_FLAG == 0 ) { TIM3_Set( 1 ); //开计数器3 } GSM_RX_BUFF[GSM_RX_FLAG++] = data; } else { GSM_RX_FLAG |= 1<<15; //接收标志强制置1 } } }上面是串口接受,由于stm的硬件buff只有一个字节,那就极可能造成字符串没接收完,就开始判断,这就会造成信息的丢失。比如说,我要提取一字符串中的某些内容,这样如果字符串没接收完就会出现你前面判断对了,但是你要提取的信息在后头,这样提取的信息就变成空的了……
原文链接:https://www.dianyuan.com/eestar/article-1731.html
实例讲解之STM32的高级捕获模式
简单介绍一下stm32的输入捕获模式
STM32的通用定时器具备基本的输入捕捉功能。所谓输入捕捉功能,是指通用定时器可以通过检测输入信号的跳变沿,检测到跳变沿的同时将计数器的当前值写入相应的寄存器。我们可以利用定制器的输入捕捉模式可以测量输入信号的高电平时间、占空比和频率。
这是定时器的内部框图
我们STM32的定时器有两种捕获模式普通输入模式和高级捕获模式(PWM输入模式)
需要注意的问题:定时器的时基频率不能太高,如果定时器工作于36M,采集50Hz的信号就会出现偏差(实测),所以程序中将定时器的时基频率配置为了1M;如果存在两个以上中断,需要设置中断优先级,否则容易出问题。
一,PWM输入模式的基本原理
PWM输入模式是输入捕捉模式的高级应用,对于测量频率较高的输入信号的频率特别精确,当然,为了实现这个模式,也得做出一点牺牲。相比于基本输入捕捉功能的实现来说,PWM输入模式中,一路输入信号同时映射到两个引脚,而且只有第一和第二通道可以配置为这种模式,换句话说,每个通用定时器只能测量一路输入信号。
PWM模式捕获方法:利用TIM2_CH1作PWM输出,TIM3_CH2捕获上述PWM信号,并测出频率和占空比。设置PWM频率为1KHz,占空比50%。
具体步骤:
- 为了实现PWM输入捕获,TIM3占用了2个通道。第2通道的电平变化会被第一通道和第二通道引脚检测到,其中第一通道被设置为从机模式(如何快速判别主从机模式,规则如下:如果设置的是第二通道作为PWM输入捕获,则剩余的第一通道都为从机,反之亦然)。
- 假设输入的PWM从低电平开始跳变,在第一个上升沿到来时,1,2通道同时检测到上升沿。而从机设置为复位模式,所以将TIM3的计数值复位至0,此时不会产生一个中断请求。
- 下一个到来的电平是下降沿,此时通道1发生捕获事件,将计数值存入通道1的CCR1里。
- 然后是第二个上升沿到来后,此时通道2发生捕获事件,将此时的计数值存入通道2的CCR2里。复位模式此时又将TIM3计数值复位至0,等待第二个下降沿到来。
- 一次捕获过程完成,则PWM的频率f=72M/CCR2;占空比:duty=(CCR1/CCR2) X100%
二、具体看看怎么配置
单片机是stm32f103,如上述所示用TIM3的CH2通道捕获PWM波,注释非常详细,可以直接调用
void tim3_pwmin_cfg(void) { TIM_ICInitTypeDef TIM_ICInitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_DeInit(TIM3); /* 定时器基本参数设置 */ /* 定时周期: TIM_Period+1 */ TIM_TimeBaseStructure.TIM_Period = 0xffff; /* 设置预分频TIM_Prescaler,输出脉冲频率:72MHz/(TIM_Prescaler+1)/(TIM_Period+1) */ TIM_TimeBaseStructure.TIM_Prescaler = 7200; /* 向上计数模式 */ TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; /* 设置时钟分频系数:不分频(这里用不到) */ TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; /*设置重复溢出次数,就是多少次溢出后进入中断,一般为0,只有高级定时器才有用*/ // TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); /* TIM3通道2*/ TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; /* 上升沿捕获*/ TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; /* 映射到 TI1 上*/ TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; /* 预分频系数,不分频*/ TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x0; /* PWM输入捕获模式是输入捕获模式的特例,初始化TIM3输入捕获参数 */ TIM_PWMIConfig(TIM3, &TIM_ICInitStructure); /*选择IC2为时钟触发源*/ TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2); /*启动定时器的被动触发*/ TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable); /*从模式控制器被设置为复位模式-选中的触发信号上升沿重新初始化计数器并产生一个更新信号 (上升沿一到,TIM4->CNT被清零,每次上升沿来到,CNT都会被清零)*/ TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset); /*捕获中断打开*/ TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE); /*使能定时器*/ TIM_Cmd(TIM3, ENABLE); /*捕获中断清除标志位*/ TIM_ClearFlag(TIM3,TIM_IT_CC2); }
中断配置,中断分组……
原文链接:https://www.dianyuan.com/eestar/article-1748.html
实例stm32f103的数字示波器(硬件+源码)
简单介绍一下数字示波器的功能
主控是stm32f103VE,采用UC/OS-II 2.9实时操作系统,使用STM32一路DA实现正弦,三角波,方波,白噪声输出。 任意一种波形幅值在0-3.3V任意可调、频率在一定范围任意可调、方波占空比可调。调节选项可以通过触摸屏完成设置。
SD卡存储: SD卡波形存储输出,能够对当前屏幕截屏,以JPG格式存储在SD卡上。能够存储1S内的波形数据,可以随时调用查看。
3. 数据传输:用C#编写上位机,通过串口完成对下位机的控制。(1)实现STOP/RUN功能(2)输出波形电压、时间参数(3)控制截屏(4)控制波形发生器(5)控制完成FFT(6)波形的存储和显示
4. 图形接口: UCGUI
5. 水平扫速: 250 ns*、500ns、1μs、5 μs、10μs、50μs、500 μs、5ms 、50ms
6. 垂直电压灵敏度:10mV/div, 20mV/div, 50mV/div, 0.1V/div, 0,2V/div, 0.5V/div, 1V/div,2V/div, 5V/div
7. 被测信号的各种参数屏幕显示,包括频率、电压峰峰值等。
看看AD采样部分电路如下
程序这块,采用定时器来触发AD转换
欢迎大家来到IT世界,在知识的湖畔探索吧! void ADC1_Mode_Config(void) { //ÅäÖÃDMA DMA_InitTypeDef DMA_csh; ADC_InitTypeDef ADC_csh; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; NVIC_InitTypeDef NVIC_InitStructure; DMA_DeInit(DMA1_Channel1); //DMA¸´Î»,ͨµÀ1 DMA_csh.DMA_PeripheralBaseAddr = ADC1_DR_Address; //ADC1µØÖ· DMA_csh.DMA_MemoryBaseAddr = (unsigned int)ADCConvertedValue; //ÄÚ´æµØÖ· DMA_csh.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_csh.DMA_BufferSize = SAMPDEPTH; //»º³å´óСΪ²ÉÑùÉî¶È DMA_csh.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //ÍâÉèµØÖ·¹Ì¶¨ DMA_csh.DMA_MemoryInc = DMA_MemoryInc_Enable; //ÄÚ´æµØÖ·×ÔÔö DMA_csh.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_csh.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_csh.DMA_Mode = DMA_Mode_Circular; //Ñ»·´«Êä DMA_csh.DMA_Priority = DMA_Priority_High; //DMAÓÅÏȼ¶¸ß DMA_csh.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1,&DMA_csh); //дÈëDMA1ÅäÖòÎÊý DMA_Cmd(DMA1_Channel1,ENABLE); //ʹÄÜDMA1ͨµÀ1 DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE); //ʹÄÜDMA CH1ÖÐ¶Ï NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); //ÅäÖÃTIM3¹¤×÷ÔÚ18MHz,ΪADÌṩ´¥·¢ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); TIM_TimeBaseStructInit(&TIM_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Period = 1; TIM_TimeBaseStructure.TIM_Prescaler = 99; //¹¤×÷ÔÚ18M£¬Ã¿¸ñ×î´óֵʱ£¬²»ÖÁÓÚÒç³ö TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure); TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update); //ʹÓÃTIM3ʼþ¸üÐÂ×÷ΪADC´¥·¢ //ÅäÖÃADC ADC_csh.ADC_Mode = ADC_Mode_Independent; //¶ÀÁ¢ADCģʽ ADC_csh.ADC_ScanConvMode = DISABLE; //¹Ø±ÕɨÃèģʽ ADC_csh.ADC_ContinuousConvMode = DISABLE; //Á¬ÐøADת»»¿ªÆô ADC_csh.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO; //ÓÉTIM3ÌṩµÄ´¥·¢Ê¼þ½øÐд¥·¢ADת»» ADC_csh.ADC_DataAlign = ADC_DataAlign_Right; //Êý¾ÝÓÒ¶ÔÆë ADC_csh.ADC_NbrOfChannel = 1; //Ҫת»»µÄͨµÀÊýÄ¿1 ADC_Init(ADC1,&ADC_csh); //дÈëADC1ÅäÖòÎÊý ADC_RegularChannelConfig(ADC1,ADC_Channel_11,1,ADC_SampleTime_1Cycles5);//²ÉÑùËÙÂÊ1M ADC_DMACmd(ADC1,ENABLE); //ʹÄÜADC1 DMA ADC_ExternalTrigConvCmd(ADC1,ENABLE); //´ò¿ªADC1Íⲿ´¥·¢ ADC_InjectedChannelConfig(ADC1,ADC_Channel_16,1,ADC_SampleTime_239Cycles5); //ÅäÖÃADC1ͨµÀ16ΪעÈëͨµÀ1 ADC_ExternalTrigInjectedConvConfig(ADC1,ADC_ExternalTrigInjecConv_None); //Èí¼þ´¥·¢×¢ÈëͨµÀµÄת»» ADC_TempSensorVrefintCmd(ENABLE); //ʹÄÜζȴ«¸ÐÆ÷ ADC_Cmd(ADC1,ENABLE); //ʹÄÜADC1 ADC_ResetCalibration(ADC1); //¸´Î»Ð£×¼¼Ä´æÆ÷ while(ADC_GetResetCalibrationStatus(ADC1)); //µÈ´ýУ׼¼Ä´æÆ÷¸´Î»Íê³É ADC_StartCalibration(ADC1); //¿ªÊ¼Ð£×¼ while(ADC_GetCalibrationStatus(ADC1)); //µÈ´ýУ׼Íê³É TIM_Cmd(TIM3,ENABLE); }
下面是主程序
int main(void) { INT8U err; SystemInit(); //³õʼ»¯RCCʱÖÓ OSInit(); LCD_Buffer_MUTEX = OSMutexCreate(4,&err); //´´½¨3¸ö¹²Ïí×ÊÔ´»¥³âÐźÅÁ¿ USART_Buffer_MUTEX = OSMutexCreate(4,&err); SDtoRAM_Buffer_MUTEX = OSMutexCreate(4,&err); OSTaskCreate(Task_Start,(void *)0,&Task_Start_Stk[TASK_START_STK_SIZE-1],TASK_START_PRIO); //ÆðʼÈÎÎñ OSStart(); }
上位机软件这块采用C#编写,也是开源的……
原文链接:https://www.dianyuan.com/eestar/article-1783.html
更多精彩内容,尽在电子星球 APP(https://www.eestar.com/)
六篇技术文章,让你秒懂电容的脾气秉性
七篇DIY技术文章献给你,让你脑洞全开
五篇文章帮你开启DSP的学习思路
汇总篇:关于PID知识,重点在此
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/102780.html