锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

【南航嵌入式系统原理与应用】第7章作业

时间:2023-02-21 14:00:01 流量传感器p11146stst三极管8550x9241ayp数字电位器

第七章作业

7-1 基于嵌入式处理器的模拟输入输出系统是如何构成的?个部分的主要功能是什么?两个系统的主要区别是什么?

答案:

  • 与模拟输入输出系统的区别:嵌入式内部大多集成A/D转换器、D/A转化器。其他的和普通模拟输入输出系统相同。
  • 嵌入式处理器模拟输入输出系统示意图
    image-20220416201708980
  • 传感器:感知或收集温度、压力、流量等相关参数
  • 信号调节电路:调整传感器发送的信号,使收集到的信号A/D的有效范围
  • A/D变换器:将模拟信号转换为数字信号
  • 处理器:根据系统需要对变换后的数字信号进行数字处理或操作
  • D/A变换器:将数字信号变成模拟信号
  • 功率放大:放大模拟信号的功率,使其自行推动后面的执行机构
  • 执行机构:将电能转化为机械能或其他能量来控制工业过程

7-5 信号滤波的基本类型是什么?各种滤波电路的特点是什么?

答案:

7-12 对于 STM32F10x 使用片上的微控制器 ADC 通道 3(PA3 作为 ADCIN3)作为电位器位置检测的例子,如图所示 7.41 所示。旋转电位器 VR1 时,ADCIN3 如果电位代表位置,假设电压发生变化 0V表示位置 0 米,3.3V 表示 100 当电位器从最低端旋转到最高端时,电位从 0 到 3.3V 变化,即位置从 0 到 100 米线性变化。试回答:

(1)写对片 DAC 初始化程序片段(包括引脚配置和 DAC 初始化)
(2)编写收集电位并改变标度的程序。

答案:

(1)写对片 DAC 初始化程序片段(包括引脚配置和 DAC 初始化)

void ADC_Configuration(void) //配置和初始化 ADC { 
             GPIO_InitTypeDef GPIO_InitStructure;  ADC_InitTypeDef ADC_InitStructure;     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|     RCC_APB2Periph_ADC1,ENABLE);//A选择A口多功能时钟(PA3为ADCIN3)     /* 配置GPIO的PA7作为ADCIN3模拟通道输入端,频率50MHz */     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_GPIO_Pin_3;//ADC1通道PA3=ADIN3引脚     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; ///管脚频率50MHz     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; ///模拟输入模式     GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO端口     /* 初始化ADC:独立模式、多通道扫描、连续转换、软件触发、ADC数据右对齐 */     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立工作模式     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数据右对齐     ADC_InitStructure.ADC_NbrOfChannel = 1;//进行规则转换的ADC通道数为1个通道
    ADC_Init(ADC1, &ADC_InitStructure);
    /* 设置ADC1使用ADCIN7转换通道,转换顺序1,采样时间为239.5周期*/ 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_7, 1, ADC_SampleTime_239Cycles5 );
    ADC_Cmd(ADC1, ENABLE); //使能ADC1
    ADC_ResetCalibration(ADC1); //使能ADC1复位校准寄存器
    while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准寄存器接收
   	ADC_StartCalibration(ADC1); //启动ADC1校准
    while(ADC_GetCalibrationStatus(ADC1)); //等待ADC1校准结束
    ADC_SoftwareStartConvCmd(ADC1, ENABLE); //启动软件转换
 }

(2)写出采集电位并进行标度变换的程序

答案:

uint16_t Temp;
float Valtage;//电压值
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
Temp = ADC_GetConversionValue(ADC1); //调用库函数获取转换值
/*假设在由电位器电位可知,当V=0V时,测算的数字量为N0=0,V=3.3V=3300mV时测算的 数字量为Nm=0xFFF,则通过标度变换公式(7.2)得到任何数字对应的电压值为: Yx=Y0+(Ym-Y0)*(Nx-N0)/(Nm-N0)=0+3300*Nx/0xFFF=3300Nx/0xFFF (mV)*/
Valtage=3300*Temp/0xFFF;//压力换算值,单位mV

7-14 简述利用片内 DAC 再通过外加运算放大电路产生指定幅度和周期的正弦波的方法和步骤。写出对STM32F10x 的 DAC 进行配置和初始化的程序片段。

(1)简述利用片内 DAC 再通过外加运算放大电路产生指定幅度和周期的正弦波的方法和步骤

答案:

​ 利用 DAC 通过外接运放产生幅度可变,周期可编程的正弦波的基本方法是首先采集一个周期正弦波的平均 N 个点如 32 个点的幅值,保存在程序存储器中或数据存储器中,然后利用定时器定时,定时长度取决于正弦波的周期,如周期为 T,则定时时间间隔 t=T/(N-1),在定时中断服务程序中输出保存在存储器中正弦的瞬时幅值,设置好初值指针,每定时时间到输出一个点,指针加一,通过(N-1)次定时中断即可输出一个周期的正弦波,当指针回零时,继续定时中断即可输出连续的正弦波。由 DAC 输出特点可知,它是 12 位 DAC,因此输出电压 Vo= DAC 输出= VREFx (DOR / 4095),在参考电压一定的情况下,输出大小取决于数字量,将公式变换为:

​ Vo=K*Dx/4095,Dx 为保存在存储器中的要输出的正弦波的点的值,K 已经考虑了参考电压,运放放大倍数等因素,因此要控制正弦波幅值只需要在程序中改变 K 的大小,而要改变正弦波的周期,只需要改变定时时间间隔。

(2)程序片段

​ 对于 STM32F10x 的 DAC 可进行如下配置:DAC 初始化包括 GPIO 引脚初始化为 DAC 引脚和 DAC 相应配置。GIO 初始化包括使能对应 DAC 通道的 GPIO 引脚时钟,使能 DAC 时钟,设置通道引脚为模拟输入。一旦使能 DACx 通道,相应的 GPIO 引脚(通道 1 的 PA4 或者通道 2 的 PA5)就会自动与 DAC 的模拟输出相连(DAC_OUT1 或 DAC_OUT2)。为了避免寄生的干扰和额外的功耗,引脚 PA4 或者 PA5 在之前应当设置成模拟输入(AIN)。

​ DAC 初始化包括选择触发方式、是否使用波形发生、关闭输出缓冲、使能 DAC、通道 1 或 2 由软件触发。设置通道 12 位右对齐模式。

​ 具体初始化及配置程序如下:

答案:

void DAC_Configuration(void)
{ 
        
    GPIO_InitTypeDef GPIO_InitStructure;
    DAC_InitTypeDef DAC_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC ,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
    RCC_APB2Periph_AFIO,ENABLE); 
    /*-----------DAC 端口配置 PA4/PA5 DAC1 通道 4 模拟输入-------------*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA ,&GPIO_InitStructure);
    DAC_DeInit(); //还原到初始状态
    /* DAC 通道 1 配置 */
    DAC_InitStructure.DAC_Trigger = DAC_Trigger_T3_TRGO; //T3 触发
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不用波形产生
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; //失能输出缓冲
    DAC_Init(DAC_Channel_1, &DAC_InitStructure); //DAC 初始化
    DAC_Cmd(DAC_Channel_1, ENABLE); //使能 DAC 通道 1 自动连接至 PA4
    DAC_SetChannel1Data(DAC_Align_12b_R,0);//通道 1 右对齐输出
}

7-15 试设计一个模拟输入输出系统,采用 STM32F10x 微控制器,采用 3.3V 供电,内置 12 位 ADC,某压力传感器输出 0-100mV 对于 0-10Mpa,压力超过 8.5Mpa 时,输出报警信号,让蜂鸣器发声,低于 8Mpa时解除报警。并将得到的压力用 4-20mA 电流输出到外部。写出相关程序片段。

答案:

按照题目要求,基于 STM32F10x 的模拟输入输出系统,必须包括模拟输入通道和模拟输出通道,系统电原理图如图所示。

模拟输入通道要将压力传感器 0-100mV 的电压信号通过调理电路(放大滤波)到 0-3.3V,因此运算放大器 U1B 放大倍数应该为 3300/100=33 倍,这里采用同相放大器,则 Rf/R1=32,如果取 R1=1K,由 Rf=32K,采用 U1A 构建的二阶有源低通滤波器,最后通过调电路输出的模拟信号接入 ADCIN1(MCU 的 PA1 引脚)。

模拟输出通道输出 4~20mA 电路,参考教材中的图 7.33。

报警输出电路由 R9/BG2/蜂鸣器组成,当 PB1(Ctrl)=1 时,三极管 BG2 导通,BJ 蜂鸣器得电发声报警,当 PB1=0 时三极管截止,蜂鸣器不响,停止报警。报警点是 8MPa,由线性标度变换可知:100mV 经过放大 33 倍后变成 3.3V,由于参考电压也是 3.3V 因此,数字量为 0xFFF=4095,由此可知:P=10/4095*Dx,Dx 为从 ADC 转换得到的数字量,把压力单位变换为 Kpa,则有
P=10000/4095*Dx (Kpa),Dx=4095*P/10000,l 因此当 8.5Mpa 时,有 D=4095/10000*8500 为报警点。
Yx=Ym-Y0+(Ym-Y0)(Nx-N0)/(Nm-N0)=4+16*(Nx-496)/(2482-496)

相关程序如下:
ADC 初始化程序详见教材 P.230,把其中的 ADCIN7 改为 ADCIN1,PA7 改为 PA1,GPIO_Pin_7 改为
GPIO_Pin_1,ADC_Channel_7 改为 ADC_Channel_1,其它不变

void ADC_Configuration(void) //配置和初始化ADC
{ 
        
    GPIO_InitTypeDef GPIO_InitStructure;
    ADC_InitTypeDef ADC_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO|
    RCC_APB2Periph_ADC1,ENABLE);//A口及A口多功能时钟选择(PA7为ADCIN7)
    /* 配置GPIO的PA1作为ADCIN1模拟通道输入端,频率50MHz */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_GPIO_Pin_1;//ADC1通道PA1=ADIN1引脚
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //管脚频率50MHz
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入模式
    GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIO端口
    /* 初始化ADC:独立模式、多通道扫描、连续转换、软件触发、ADC数据右对齐 */
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立工作模式
    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数据右对齐
    ADC_InitStructure.ADC_NbrOfChannel = 1;//进行规则转换的ADC通道数为1个通道
    ADC_Init(ADC1, &ADC_InitStructure);
    /* 设置ADC1使用ADCIN1转换通道,转换顺序1,采样时间为239.5周期*/ 
    ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5 );
    ADC_Cmd(ADC1, ENABLE); //使能ADC1
    ADC_ResetCalibration(ADC1); //使能ADC1复位校准寄存器
    while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准寄存器接收
    ADC_StartCalibration(ADC1); //启动ADC1校准
    while(ADC_GetCalibrationStatus(ADC1)); //等待ADC1校准结束
    ADC_SoftwareStartConvCmd(ADC1, ENABLE); //启动软件转换
}

DAC 初始化程序 详见教材 P.236,这里由于使用的通道均为 DAC1 即用 PA4 引脚,程序不用修改直接引用。具体程序如下:

void DAC_Configuration(void)
{ 
        
    GPIO_InitTypeDef GPIO_InitStructure;
    DAC_InitTypeDef DAC_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC ,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO,ENABLE); 
	/*-----------DAC 端口配置 PA4/PA5 DAC1 通道 1 模拟输入-------------*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA ,&GPIO_InitStructure);
    DAC_DeInit(); //还原到初始状态
    /* DAC 通道 1 配置 */
    DAC_InitStructure.DAC_Trigger = DAC_Trigger_T3_TRGO; //T3 触发
    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None; //不用波形产生
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Disable; //失能输出缓冲
    DAC_Init(DAC_Channel_1, &DAC_InitStructure); //DAC 初始化
    DAC_Cmd(DAC_Channel_1, ENABLE); //使能 DAC 通道 1 自动连接至 PA4
    DAC_SetChannel1Data(DAC_Align_12b_R,0);//通道 1 右对齐输出
}

将压力转换成 4-20mA 的电流,0Mpa 对应 4mA,10Ma 对应 20mA,要通过图示电路输出 4mA 时,需要从 DAC 输出 0.4V 电压,因此对应数字量为 0.4*4095/3.3=496输出 20mA 要求 DAC 输出的电压为 2V,因此数字量为 2*4095/3.3=2482,

按照线性标度变换可知:

N0=496,Nm=2482,Ym=20,Y0=4,Yx=Ym-Y0+(Ym-Y0)(Nx-N0)/(Nm-N0)=4+16*(Nx-496)/(2482-496)

Yx=4+16(Nx-496)/1986 ,Nx>=496

现在看输出与输入的关系:输入 0 时放大后也是 Din0=0,对应 ADC 数字量 0,输出应该 4mA,电压为 0.4V,数字量 Dout0=496,输入 100mV 放大后 3.3V 时对应 ADC 数字量 Dinm=4095,输出应该是 20mA,输出电压为 2V,对应数字量为Doutm=2482,

输入任何电压(放大后)对应数字量 Doutx 为:

Doutx=Dout0+(Doutm-Dout0)*(Dinx-0)/(Dinm-Din0)=496+(2482-496)Dinx/4095=496+1986Dinx/4095

Doutx=496+1986Dinx/4095,用 Doutx 代入上述 Yx 的 Nx 得:

Yx=4+16(496+1986Dinx/4095-496)/1986

Yx=4+16*Dinx/4095,显示当 Dinx=0 时输出 4mA,Dinx=4095 时输出 20mA,编程时,只需要通过 DAC 输出 Doutx=496+1986Dinx/4095 即可输出 4-20mA 电流,其中 Dinx 为采集压力信号对应的数字量。

main()
{ 
        
    float P_Value;//压力值,单位 Kpa
	uint16_t DataIn,DataOut;
	:系统初始化、ADC 初始化、DAC 初始化、PB1 初始化为推挽输出初始化
	while(1)
    { 
        
    	while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束
   		DataIn = ADC_GetConversionValue(ADC1); //获取转换值
        P_Value=10000/4095*DataIn;//压力换算值,单位 Kpa
        if (P_Value>8500) GPIO_SetBits(GPIOB,GPIO_Pin_1);//报警输出蜂鸣器响
        else GPIO_ResetBits(GPIOB,GPIO_Pin_1);//报警输出撤消,蜂鸣器停止响声
        DataOut=496+1986Dinx/4095;//取待输出的数字量(与输入对应的电压通过电流转换为 4-20mA 电流)
        DAC_SetChannel1Data(DAC_Align_12b_R, DataOut);//以 12 位右对齐方式输出 Value 数字量
    }
}
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章