[其他ST产品] STM32F1常用外设介绍

[复制链接]
 楼主| 范德萨发额 发表于 2023-2-28 20:36 | 显示全部楼层
ADC规则组通道配置函数

它的作用是给序列每个位置填写的指定的通道,就是填写点菜点菜的过程

void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);

 楼主| 范德萨发额 发表于 2023-2-28 20:37 | 显示全部楼层
外部触发转换控制函数
是否允许外部触发转换

void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
 楼主| 范德萨发额 发表于 2023-2-28 20:37 | 显示全部楼层
ADC获取转换值函数

获取AD转换的数据寄存器,读取转换结构就需要使用这个函数

uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
 楼主| 范德萨发额 发表于 2023-2-28 20:38 | 显示全部楼层
ADC获取双模式转换值

读取双ADC模式转换结果的函数

uint32_t ADC_GetDualModeConversionValue(void);
 楼主| 范德萨发额 发表于 2023-2-28 20:38 | 显示全部楼层
注入组相关函数

void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
 楼主| 范德萨发额 发表于 2023-2-28 20:38 | 显示全部楼层
配置模拟看门狗相关函数

void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);//是否启动模拟看门狗
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold, uint16_t LowThreshold);//配置高低阈值
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);//配置看门的通道
 楼主| 范德萨发额 发表于 2023-2-28 20:38 | 显示全部楼层
用来控制开启内部的两个通道函数

用来控制开启内部的两个通道(ADC温度传感器,内部参考电压控制),如果要用到这两个通道需要调用这个函数

void ADC_TempSensorVrefintCmd(FunctionalState NewState);
 楼主| 范德萨发额 发表于 2023-2-28 20:38 | 显示全部楼层
获取标志位状态函数

FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
 楼主| 范德萨发额 发表于 2023-2-28 20:39 | 显示全部楼层
清除标志位函数

void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG);
 楼主| 范德萨发额 发表于 2023-2-28 20:40 | 显示全部楼层
获取中断状态函数

ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
 楼主| 范德萨发额 发表于 2023-2-28 20:40 | 显示全部楼层
清除中断挂起位

void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);
 楼主| 范德萨发额 发表于 2023-2-28 20:46 | 显示全部楼层
ADC程序实例
  1. void AD_Init(void)
  2. {
  3.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  4.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  5.        
  6.         RCC_ADCCLKConfig(RCC_PCLK2_Div6);
  7.        
  8.         GPIO_InitTypeDef GPIO_InitStructure;
  9.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  10.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;
  11.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  12.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  13.                
  14.         ADC_InitTypeDef ADC_InitStructure;
  15.         ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//独立模式
  16.         ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
  17.         ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;//软件触发
  18.         ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//连续模式
  19.         ADC_InitStructure.ADC_ScanConvMode = DISABLE;//扫描模式
  20.         ADC_InitStructure.ADC_NbrOfChannel = 1;//通道数
  21.         ADC_Init(ADC1, &ADC_InitStructure);
  22.        
  23.         ADC_Cmd(ADC1, ENABLE);//开启ADC
  24.        
  25.         ADC_ResetCalibration(ADC1);//开始复位校准
  26.         while (ADC_GetResetCalibrationStatus(ADC1) == SET);//获取复位校准状态
  27.         ADC_StartCalibration(ADC1);//开始校准
  28.         while (ADC_GetCalibrationStatus(ADC1) == SET);//获取校准状态
  29. }

  30. uint16_t AD_GetValue(uint8_t ADC_Channel)
  31. {
  32.         ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);//设置规则组的函数
  33.         ADC_SoftwareStartConvCmd(ADC1, ENABLE);//软件触发
  34.         while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);//获取校准完成标志位
  35.         return ADC_GetConversionValue(ADC1);//返回转换完的AD值
  36. }

 楼主| 范德萨发额 发表于 2023-2-28 20:47 | 显示全部楼层
DMA

    DMA(Direct Memory Access)直接存储器存取,主要是用来协助CPU,完成数据转运的工作

    DMA可以提供外设(外设寄存器,一般是外设的数据寄存器DR,Data Register,比如ADC的数据寄存器,串口的数据寄存器)和存储器(运行内存(SRAM)和程序存储器(Flash)是存储变量数组和程序代码的地方)或者存储器与存储器之前的高速数据传输,无须CPU干预,节省了CPU的资源

    12个独立可配置的通道(数据转运的路径):DMA1(7个通道),DMA2(5个通道)

    每个通道都支持软件触发和特定的硬件触发,存储器到存储器的数据转运,一般用软件触发,外设到存储器的转运一般用硬件触发

    STM32F103C8T6 DMA资源:DMA1(7个通道)
 楼主| 范德萨发额 发表于 2023-2-28 20:47 | 显示全部楼层
存储器映像
5426863fdf7d3ccc83.png
计算机系统的5大组成部分:运算器、控制器、存储器、输入设备和输出设备,运算器和控制器一般合在一起叫做CPU,计算机的核心关键部分就是CPU和存储器,存储器最重要的是存储器的内容和存储器的地址。
 楼主| 范德萨发额 发表于 2023-2-28 20:47 | 显示全部楼层
存储器分为两大类:ROM和RAM,ROM就是只读存储器,是一种非易失性、掉电不丢失的存储器,RAM就是随机存储器,是一种易失性、掉电丢失的存储器,ROM分为三块,第一块是程序存储器,Flash,也就是主闪存,用途就是存储C语言编译后的程序代码,也就是下载程序的位置,运行程序一般也是从主闪存中开始运行的,系统存储器和选项字节,这两块存储器也是ROM的一种,掉电不丢失,实际上它们的存储介质也是Flash,非主闪存Flash,系统存储器是用来存储BootLoader,BootLoader程序一般是芯片出厂自动写入的,一般不允许修改,选项字节存的主要是Flash的读保护、写保护,还有看门狗等等的配置,运行内存SRAM存储我们程序中定义变量、数组、结构体的地方,外设寄存器存储的是我们初始化各个外设,最终读写的东西,外设寄存器起始也是SRAM,存储内核外设NVIC和SysTick。
 楼主| 范德萨发额 发表于 2023-2-28 20:47 | 显示全部楼层
DMA的框图 4961163fdf7eeabdf1.png
 楼主| 范德萨发额 发表于 2023-2-28 20:48 | 显示全部楼层
左上角是Cortex-M3内核,里面包含了CPU和内核外设,剩下的所有东西都可以看成是存储器,Flash是主闪存,SRAM是运行内存,各个外设都可以看成是寄存器,也是一种SRAM存储器,寄存器是一种特殊的存储器,一方面,CPU可以对寄存器进行读写,就像读写运行内存一样,另一方面,寄存器的每一位背后,都连接了一根导线,这些导线可以控制外设电路的状态,比如置引脚的高低电平,导通和断开、切换数据寄存器,或者多位结合起来,当做计数器、数据寄存器,寄存器是连接软件和硬件的桥梁,软件读写寄存器,就相当于在控制硬件的执行,使用DMA进行数据转运,就相当于从某个地址取内容,再放到另一个地址去。
 楼主| 范德萨发额 发表于 2023-2-28 20:48 | 显示全部楼层
为了高效有条理地访问存储器,设计了一个总线矩7阵,总线矩阵的左端,是主动单元,也就是拥有存储器的访问权,右边这些,就是被动单元,它们的存储器只能被左边的主动单元读写,主动单元内核有DCode和系统总线,可以访问右边的存储器,其中DCode总线是专门访问Flash的,系统总线是访问其他东西的,由于DMA要转运数据,所以DMA也必须要有访问的主动权,主动单元除了内核、CPU剩下的就是DMA总线了,DMA1和DMA2都各自有一条总线,下面以太网外设自己也私有一个DMA总线,DMA1有7个通道,DMA2有5个通道,各个通道可以分别设置它们转运数据的源地址和目的地址,下面的仲裁器,由于DMA只有一条总线,仲裁器可以根据通道的优先级决定哪个通道谁先用,在总线矩阵里,也有一个仲裁器,如果DMA和CPU都要访问同一个目标,那么DMA就会暂停CPU的访问,以防止冲突,不过总线仲裁器,仍然会保证CPU得到一半的总线带宽,使CPU也能正常工作,下面的AHB从设备,也就是DMA自身的寄存器,DMA作为一个外设,也会有自己相应的配置寄存器,连接上了总线右边的AHB总线上,所以DMA既是总线矩阵的主动单元,可以读写各种存储器,也是AHB总线上的被动单元,DMA请求就是DMA的硬件触发源,比如说ADC转换完成、串口接收到数据需要触发DMA转运数据的时候,就会通过这条线路,向DMA发出硬件触发信号,之后DMA就可以执行数据转运的工作了,这就是DMA请求的作用。15
 楼主| 范德萨发额 发表于 2023-2-28 20:48 | 显示全部楼层
Flash是ROM只读存储器的一种,如果通过总线直接访问的话,无论是CPU,还是DMA,都是只读的,只能读取数据,而不能写入,如果DMA的目的地址,填写了Flash的区域,那转运时就会出错。也可以配置Flash接口控制器,对Flash进行写入,先对Flash进行擦除,再写入数据。
 楼主| 范德萨发额 发表于 2023-2-28 20:49 | 显示全部楼层
DMA的基本结构图 4021263fdf83d021c8.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 在线客服 返回列表 返回顶部
快速回复 在线客服 返回列表 返回顶部