嵌入式
整流电路
整流电路分为哪几种:
整流电路根据电路结构和用途的不同分为两大类:
- 测量仪表使用的线性整流电路,这类电路要求波形畸变小,线性度好。多用运算放大器与检波二极管共同构成。
- 为直流负载供电的电源整流电路,这类电路要求成本低,效率高。对波形畸变没有要求。
这一类整流电路常见的有四种:
- 半波整流电路:电路中使用一只整流二极管构成一组整流电路;
- 全波整流电路:电路中使用两只整流二极管构成整流电路;
- 桥式整流电路:电路中使用四只整流二极管构成一组整流电路;
- 倍压整流电路:电路中至少使用两只整流二极管构成一组整流电路。
- 整流电路:是把交流电能转换为直流电能的电路。
- 整流电路通常由主电路、滤波器和变压器组成。
整流电路的作用:
整流:把交流电变换成*似直流电的电路。最原始的整流电路为半波整流,也就是在交流回路中串接一个二极管,利用二极管的单向导通性,将交流电的负半波切去,只保留间隔一个半波时隙的正半波,因为没有负半波而只有正半波的脉动电动势,故称半波整流更高一级的是全波整流,四个背对背的二极管构成全波整流电路,把交流电的负半波反转后填到两个正半波之间的时隙中,使电源电流波形成为连续起伏的*似直流电。
整流电路是电源电路中心的核心电路,它的作用是将交流电压通过整流二极管(通常是整流二极管,当然还可以使用其他元器件)转换成单向脉动性的直流电压,整流是将交流电压转换成直流电压过程中的关键一步。
无论什么类型的电源电路,都需要整流电路来完成交流电至直流电的转换。整流电路的类型比较少,但具体电路的变化比较多,电子电路中基本的整流电路有三种:半波整流电路、全波整流电路和桥式整流电路。
整流电路的故障发生率比较高,主要是整流二极管因为过留而损坏,出现二极管开路或击穿故障。主要的检修方法是测量整流二极管的正反向电阻。
晶闸管
导通条件:正向的阳极电压;正向的门极电流(门极触发电流需要一定幅值)。两者缺一不可。
导通后门极失去作用:晶闸管一旦导通,门极就失去控制作用。
导通到阻断:要使已导通的晶闸管关断,则要使阳极电流小于某个电流值,方法:
1)降低电压包括加反压;
2)改变负载比如增加负载电阻。
反向截止:承受反向电压,晶闸管不能导通。
三种状态:导通状态、正向阻断状态、反向截止状态。
————————————————
版权声明:本文为CSDN博主「欲读万卷书,不入愚昧途」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45589295/article/details/123123270
PFC
全称(Power Factor Correction),功率因数校正
分为主动式和被动式,是一种提高电路功率因数的电路,清除电路里的容性和感性带来的无功功率。
图腾柱
电流检测
高侧法和低侧法
运算放大器
差分信号
定义:幅值相同,相位相反的信号
特点和存在的意义:抗电磁干扰,
差模信号
定义:差分信号的差值
共模信号
定义:两个差分电压的*均值
运放的原理
非线性工作区
在负输入端和输出端负反馈的前提下,运放才会工作在线性区
- 虚短:正负输入端电压几乎相同,就像短路一样
- 虚断:正负输入端电流几乎为0,像断开一样
应用
-
加法器
-
减法器
-
对数电路
-
指数短路
-
乘法器
-
除法器
-
积分电路
-
微分电路
-
比例放大电路
线性工作区
直接差模放大
运放主要参数
-
开环电压增益:输出电压与输入电压差值放大的倍数
-
输入失调电压、电流、偏置电流:使输入输出端悬空的时候,由于运放内部元器件不对称,在供电的情况下,输出端会有电压输出,在输入端口接入电压和电流, 使得输出端的电压为零的电压和电流,叫输入失调电压电流,两个输入端的失调电流的*均值,叫做偏置电流
-
共模抑制比:
差模增益比共模增益取dB,一半都是60~80dB,是运放重要的性能参数
-
压摆率:运放的输出最快响应速度
-
建立时间:当输入信号改变时,输出要用多长时间来稳定下来
-
单位增益带宽:上限截止频率,当增益为0时,工作频率
-
噪声
直流减速电机驱动芯片TB6612FNG
引脚图
PWM
高精度PWM(HRTIM)
这块F334是专门针对开关电源和高频信号处理的而研发的,内部集成了一个比以前的高级定时器TIM1/TIM8还要高级的定时器,即高分辨率定时器HRTIM,因为功能更强大所以配置起来也很麻烦,对于第一次使用它的人来说简直看得眼花缭乱。
HRTIM的时钟频率可以通过倍频最高可以达到4.608GHz,F334的普通高级定时器TIM1最高才72MHz!!!超高的时钟频率意味着在需要产生高频PWM波的时候也能保持超高的精度,这正是数控开关电源中所需要的。举个例子:要求产生1MHz的PWM波时,如果使用72MHz的TIM1来做,不分频,则ARR的值只能设为72,也就是说 0 - 72 对应占空比 0 - 100% 显然精度太差了。如果使用4.608GHz的HRTIM来做,则ARR的值要设为4608,即 0 - 4608 对应 0 - 100% 的占空比,可见精度大幅度提高了。
注意:HRTIM1里面有TimerA、TimerB、TimerC、TimerD一共4个子定时器,每个子定时器2个输出通道。还有一个TimerE无输出通道的。。。。。
子定时器的重装载寄存器ARR改名了,叫做PER;比较值寄存器CCR也改名了,叫做CMP。
配置














配置代码
HAL_HRTIM_WaveformOutputStart(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //通道打开
HAL_HRTIM_WaveformCounterStart(&hhrtim1, HRTIM_TIMERID_TIMER_A); //开启子定时器A
修改频率和占空比
hhrtim1.Instance->sTimerxRegs[1].PERxR = 50000;//通过修改重装载值PER,从而修改PWM的频率
hhrtim1.Instance->sTimerxRegs[1].CMP1xR = 11504;//通过修改比较值CMP,从而修改占空比
SPWM(逆变算法)
SPWM原理
逆变是一个成熟的技术,无论是单极性逆变还是双极性逆变,都离不开SPWM调制。SPWM逆变的精髓就是【冲量等效原理】——将一周期正弦波等分为N段,每段的长度为T,可以算出任意一段的积分面积S(即正弦波在T时间段内与横轴围成的面积),如果在每一段T时间段内,SPWM波与横轴围成的面积都等于T内正弦波的定积分S,那么在后级对SPWM进行滤波后即可得到正弦波。

如上图所示,只要能控制单片机输出这样的SPWM波,即可通过滤波得到正弦波。
那么如何让单片机输出这样的波形呢?主要分以下几步:
确定载波频率 fb
载波即下图中红线标出的波形,占空比的调整都在每个载波周期内进行。对于单片机,我们只需要控制在某个载波周期内,高低电*所占的时间即可。一般来讲,载波频率越高,滤出的正弦波越细腻,能调出的正弦波频率上限也越高。
确定正弦波频率 fs
我们需要的正弦波的频率。
得到正弦波一周波分段 N
N = fb / fs ,由此可见,正弦波频率越低,N越大,基波频率越低,N越小。
分段计算正弦波积分 S,得出PWM占空比序列。
这里的分段计算,就是在整个正弦波一周期内,依次计算。计算出每段S后,另PWM与横轴围成的面积等于S,即可得出该段的PWM占空比。一周期计算完成后,即得出了PWM的占空比序列。
单片机输出SPWM
得到PWM序列后,其实就是个一维数组,写入单片机后,在每个定时器中断中更新占空比即可。
SPWM序列生成
掌握以上原理后,需要先通过软件计算生成spwm序列,根据以上原理,编写matlab程序如下:
%-----硬件设置-------------------------------------
timerCLK = 160000000;%timer时钟,160MHz/1分频
ARR = 7999;
baseRate = timerCLK / (ARR + 1);%载波频率
%-----正弦波设置------------------------------------
F = 25;%频率
T = 1/F;%周期
ampScale = 0.85;%调幅
N = round(baseRate / F);%一周波分多少段
stepTime = 1/F/N;%积分步进值
%-----计算------------------------------------------
CCR = (1:1:N)';
for i=1:1:N
area = double(quad(@(x)sin(2*pi*F*x),(i-1)*stepTime,i*stepTime));
CCR(i) = round((ampScale*area*ARR / stepTime + ARR) / 2);
end
这里的timerCLK即STM32 TIMER1的时钟频率,ARR即定时器重载值,这样就得到了载波频率。
然后对正弦波的各个参数进行设置,最后的for循环便计算了每一段的正弦波积分面积,并根据积分面积计算出高电*计数CCR。这样一来,将CCR序列放入单片机中,在每个定时器中断更新CCR即可。
THD
一、THD(总谐波失真)概述
THD是英文Total Harmonic Distortion的缩写,意为总谐波失真。 电学中,谐波是相对于基波而言的,一个频率为f1的正弦电压信号,施加在诸如整流器等非线性设备上,其电流信号发生失真,不再是纯正的正弦波。而是相当于频率为f1的正弦波(基波)与若干频率为f1的整数倍的正弦波(谐波)的叠加。这里的谐波,是引起电流信号失真的原因,这种现象,我们称为谐波失真。总谐波失真(THD)用于所有谐波引起的波形失真的程度。 图为六脉整流变频器的输入电压和电流波形,上方波形窗口中的电压波形为纯正的正弦波,而下方波形窗口中显示的电流波形已经发生了严重的谐波失真。谐波失真由非线性器件二极管导致,由于一个周波中,二极管开通6次,所以呈现六个脉冲波。

二、THD(总谐波失真)的测量
从总谐波失真的计算公式可知,总谐波失真的数值与谐波次数的上限值H密切相关。一般的谐波测量设备如谐波分析仪等,大多适用于电网谐波测量,其上限值通常在40次以内。 对于变频器等包含较高次谐波的谐波发射设备,测量总谐波失真需要采用可以测量更高次谐波的专用谐波检测仪器如:变频功率分析仪。此外,对于高电压、大电流系统,还需注意所用的传感器具有必要的带宽如:变频功率传感器。

DQ坐标变换
两个正交正弦量,变换为恒定的值
ARM的中断处理机制
ARM异常源
ADC
STM32中的Differential(单端模式)模式和signed ended(差分模式)模式
| *Single-ended*输入模式 | *Differential*输入模式 | |
|---|---|---|
| 硬件信号线连接方式 | 对于每一个信号源,都有一根线,连接到你所用到的数据采集接口上。 | 两根信号线,连接对应的信号源。每一根接到对应的输入端,比如a+和a-。 |
| 数据采集方式 | 测量信号与地(ground)之间的差别 | 有两个高阻抗的功率放大器,检测输入端与接口地端之间的电压。还有第三个功率放大器,用来算出前两个功放所测得的电压,即a+和a-,之间差值。这样就排除了两者之间公共的电压所带来的影响。 |
| 用此法的前提 | (1)信号线是接地的(2)采样设备的ground和信号源的ground是相同的(值) | |
| 缺点 | (1)地电*差异:一般设备是认为ground是0V的常量,但是实际上,不同的位置,常有不同的电*。两者位置越接*,电*越接*于相同。但是如果将两者的地连接在一起的话,电*差值会导致一个大电流,即接地回路。这会导致在使用Single-ended模式输入的时候会出错。(2)噪音错误:Single-ended模式输入对于噪音错误很敏感。噪音,即非期望的信号组合。由于信号线就像天线,会捕获环境电子活动,导致了噪音的产生。而对于Single-ended模式,是无法区分噪音和实际信号的。 使用differential输入,可以解决接地和噪音的问题。 | (1)信号浮空:使用差分模式最常见的一个问题就是忘了将某个连接接地,即浮空。例如电池供电的设备和热电偶没有接地的连接。例如,你可以在+和–输入之间接上一个电池。然后两个输入放大器会去监视+到地的电压和–到地的电压。然而,由于没有电池和地之间没有连接,这些测得的电压可能是任何的值,也许就就会超过放大器的处理范围。对于这些浮空的信号源,应当提供一个参考源。比如Microlink有一个标示为0V的插槽。从“–”线上连一个连到这个0V的插槽,或者直接通过一个电阻相连,即可解决此问题。而如果你的信号本身是自接地的,那么就不需要接这个0V了。(2)三个用来差分输入检测的放大器,总称为设备放大器。如前所述,理想情况下,对于两根线共有的电压,都可以因差分计算而被消除掉。而实际上,两个输入放大器,并不能完美的互相匹配,因此对于公共电压,多少会出现一些差别的。对于设备放大器接*于理想情况的程度大小,可以表述为共模抑制比,单位是分贝。此参数越高越好。另外需要考虑的一点是,公共电压的范围,即放大器所能处理的最大的公共电压,如果环境电压超过此阈值,那么测量结果就不准确了。(你的硬件操作范围也许可以设计的比公共电压范围更大,但是操作电压范围只能保证你的硬件不会被损坏,却不能保证一定能正常工作。)(3)差分输入需要更少的信号?差分输入和Single-ended输入相比,有一个显而易见的缺点:你需要两倍数目的线,然后你才可以连接到一半数目的信号。如果你只有更短的信号线,信号线之间更*,信号大于100mV的话,经过评估,觉得用Single-ended输入,对你也是OK的,这时,你可以在Single-ended输入模式中使用差分输入模式。具体做法是,短路其中一根信号线(通常是短路输入端)接到V输入上。这样的话,差分输入,就可以提供两种模式任你选了。 |
| 优点 | 解决了Single-ended模式所具有的问题,即,(只要他们的电压不是太大,而使得功法无法处理的话)使用此法测得的值,是与接地无关的。同样地,此法中,两个信号线,如果有噪音,那么也是相同的,而做了差值后,也就消除了,减去了噪音的干扰。 |
ADC原理
Analog-to-Digital Converter的缩写。指模/数转换器或者模拟/数字转换器。是指将连续变量的模拟信号转换为离散的数字信号的器件。
典型的模拟数字转换器将模拟信号转换为表示一定比例电压值的数字信号。
简单地说就是将模拟电压值,转换成对应的肉眼可读数值
12位ADC是一种逐次逼*型模拟数字转换器。它有,3个ADC控制器,多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。
12位模拟数字转换器
就是ADC的数字存储是12位的 也就是说转换器通过采集转换所得到的最大值是4095 “111111111111”=4095 二进制的12位可表示0-4095个数, 对应着所测电压的实际值,转换的电压范围是0v-3.3v的话,转换器就会把0v-3.3v*均分成4096份。设转换器所得到的值为x,所求电压值为y。

CubeADC设置
ADCs_Common_Settings ADC模式设置
Mode ADC_Mode_Independent
这里设置为独立模式
独立模式模式下,双ADC不能同步,每个ADC接口独立工作。所以如果不需要ADC同步或者只是用了一个ADC的时候,应该设成独立模式,多个ADC同时使用时会有其他模式,如双重ADC同步模式,两个ADC同时采集一个或多个通道,可以提高采样率
Data Alignment (数据对齐方式): 右对齐/左对齐
这个上方有讲解,数据的左右对齐
Scan Conversion Mode( 扫描模式 ) : DISABLE
如果只是用了一个通道的话,DISABLE就可以了(也只能DISABLE),如果使用了多个通道的话,会自动设置为ENABLE。 就是是否开启扫描模式
Continuous Conversion Mode(连续转换模式) ENABLE
设置为ENABLE,即连续转换。如果设置为DISABLE,则是单次转换。两者的区别在于连续转换直到所有的数据转换完成后才停止转换,而单次转换则只转换一次数据就停止,要再次触发转换才可以进行转换
Discontinuous Conversion Mode(间断模式) DISABLE
因为我们只用到了1个ADC,所以这个直接不使能即可
规则通道设置
Enable Regular Conversions (启用常规转换模式) ENABLE
使能 否则无发进行下方配置
Number OF Conversion(转换通道数) 1
用到几个通道就设置为几
多个通道自动使能扫描模式

Extenal Trigger Conversion Source (外部触发转换源)
设定ADC的触发方式

Regular Conversion launched by software 规则的软件触发 调用函数触发即可
Timer X Capture Compare X event 外部引脚触发,
Timer X Trigger Out event 定时器通道输出触发 需要设置相应的定时器设置
这个具体在上方ADC框图的5部分有讲解
Rank 转换顺序
这个只修改通道采样时间即可 默认为1.5个周期

多个通道时会有多个Rank,可以设定每个通道的转换顺序
ADC总转换时间如下计算:
TCONV = 采样时间+ 12.5个周期
当ADCCLK=14MHz(最大),采样时间为1.5周期(最快)时,TCONV =1.5+12.5=14周期=1μs。
因此,ADC的最小采样时间1us(ADC时钟=14MHz,采样周期为1.5周期下得到) 这个上方也有讲解
注入通道设置
也就是注入通道的设置,和转换通道没啥太大区别,这里不再详解

WahchDog
Enable Analog WatchDog Mode(使能模拟看门狗中断)
这个上方有讲解,本质也测量值就是超出测量范围或者低于最低范围,启动看门狗
具体的配置看下图:
ADC转换结束中断

ADC的DMA传输

GPIO的模式为模拟模式

常用的HAL库函数
GPIO
/**
* @:GPIO初始化
* @:HAL_GPIO_Init(GPIOA, GPIO_PIN_9)
*/
HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
/**
* @:GPIO反初始化
* @:HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9)
*/
HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
/**
* @:GPIO引脚读取
* @:HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9)
* @:GPIO_PinState 返回值类型/0或1
* typedef enum
{
GPIO_PIN_RESET = 0U,
GPIO_PIN_SET
}GPIO_PinState;
*/
GPIO_PinState
HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
/**
* @:GPIO写状态
* @:HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9,GPIO_PIN_RESET)
* @:第二个参数:GPIO_PIN_RESET/GPIO_PIN_SET
*/
void
HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
/**
* @:GPIO电*反转
* @:HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_9)
*/
void
HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
/**
* @:GPIO电*状态锁定
* @:HAL_GPIO_LockPin(GPIOF,GPIO_PIN_9)
* @:typedef enum
{
HAL_OK = 0x00U,
HAL_ERROR = 0x01U,
HAL_BUSY = 0x02U,
HAL_TIMEOUT = 0x03U
} HAL_StatusTypeDef
*/
HAL_StatusTypeDef
HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
/**
* @:GPIO外部中断服务函数
* @:HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_9)
*/
void
HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
/**
* @:GPIO中断回调函数,用于写逻辑
* @:HAL_GPIO_EXTI_Callback(GPIO_PIN_9)
* {
* if(GPIO_Pin==GPIO_PIN_9) /判断哪个引脚/
* }
*/
__weak void
HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
UART
/**
* @brief 串口初始化(还有好几个初始化模式,一般用不到)
* @param 句柄,(哪个串口)
* @retval 0-ok,1-error,2-busy,3-timeout(上面写的有)
* @eg: HAL_UART_Init(&huart1);
*/
HAL_StatusTypeDef
HAL_UART_Init(UART_HandleTypeDef *huart)
/**
* @brief 反串口初始化
* @param 句柄,(哪个串口)
* @retval 0-ok,1-error,2-busy,3-timeout(上面写的有)
* @eg: HAL_UART_DeInit(&huart1);
*/
HAL_StatusTypeDef
HAL_UART_DeInit(UART_HandleTypeDef*huart);
/**
* @brief 串口发送
* @param 句柄,要发送的数据,数据大小,超时时间
* @retval 0-ok,1-error,2-busy,3-timeout(上面写的有)
* @eg: HAL_UART_Transmit(&huart2, (uint8_t *)"helloworld", 10, 0xFFFF);
*/
HAL_StatusTypeDef
HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
/**
* @brief 串口接收
* @param 句柄,要保存接收数据的指针/数组,接收数据大小,超时时间
* @retval 0-ok,1-error,2-busy,3-timeout(上面写的有)
* @eg: HAL_UART_Receive(&huart2, databuf, 10, 0xFFFF);
*/
HAL_StatusTypeDef
HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout);
/**
* @brief 中断模式发送
* @param huart:句柄
* @param pData:要发送的指针或数组
* @param Size: 要发送的数据量
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
/**
* @brief 中断模式接收
* @param huart:句柄
* @param pData:要保存接收数据的指针或数组
* @param Size: 要接收的数据量
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
/**
* @brief DMA模式发送
* @param huart:句柄
* @param pData:要发送的指针或数组
* @param Size: 要发送的数据量
* @retval HAL status
* @eg HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Senbuff, sizeof(Senbuff)); //串口发送Senbuff数组
*/
HAL_StatusTypeDef
HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
/**
* @brief DMA模式接收
* @param huart:句柄
* @param pData:要保存接收数据的指针或数组
* @param Size: 要接收的数据量
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
/**
* @brief 暂停DMA发送
* @param huart:句柄
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_UART_DMAPause(UART_HandleTypeDef *huart);
/**
* @brief 恢复DMA发送
* @param huart:句柄
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_UART_DMAResume(UART_HandleTypeDef *huart);
/**
* @brief 停止DMA发送
* @param huart:句柄
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_UART_DMAStop(UART_HandleTypeDef *huart);
/**
* @brief 几个不常用的终止正在进行的传输
* @param huart:句柄
* @retval HAL status
*/
//阻塞模式
HAL_StatusTypeDef
HAL_UART_Abort(UART_HandleTypeDef *huart);
HAL_UART_AbortTransmit(UART_HandleTypeDef *huart);
HAL_UART_AbortReceive(UART_HandleTypeDef *huart);
//中断模式
HAL_StatusTypeDef
HAL_UART_Abort_IT(UART_HandleTypeDef *huart);
HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart);
HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart);
/**
* @brief 处理中断请求
* @param huart: &huart1
* @retval None
*/
void
HAL_UART_IRQHandler(UART_HandleTypeDef *huart);
/**
* @brief 发送回调函数
* @param huart: &huart1
* @retval None
*/
__weak void
HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
/**
* @brief 接收回调函数
* @param huart: &huart1
* @retval None
*/
__weak void
HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);
/**
* @brief 串口返回状态
* @param huart: &huart1
* @retval None
*/
HAL_UART_StateTypeDef
HAL_UART_GetState(UART_HandleTypeDef *huart);
TIM
/" ##### Time Base functions ##### "/
/" ####### 定时器基础功能 ######### "/
/**
* @brief 初始化定时器
* @param htim : &htim1
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_Base_Init(TIM_HandleTypeDef *htim);
/**
* @brief 取消初始化定时器
* @param htim : &htim1
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_Base_DeInit(TIM_HandleTypeDef *htim);
/**
* @brief 启动定时器
* @param htim : &htim1
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_Base_Start(TIM_HandleTypeDef *htim);
/**
* @brief 停止定时器
* @param htim : &htim1
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim);
/**
* @brief 中断模式下启动定时器
* @param htim : &htim1
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim);
/**
* @brief 中断模式下停止定时器
* @param htim : &htim1
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim);
/**
* @brief DMA模式下启动定时器
* @param htim : &htim1
* @param pdata:原缓冲区地址
* @param 从内存传输到外设的数据长度
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_Base_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length);
/**
* @brief DMA模式下停止定时器
* @param htim : &htim1
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_Base_Stop_DMA(TIM_HandleTypeDef *htim);
PWM
==========================================================
##### Time PWM functions #####
==========================================================
"配置通道"
HAL_StatusTypeDef
HAL_TIM_PWM_ConfigChannel(TIM_HandleTypeDef *htim, TIM_OC_InitTypeDef* sConfig, uint32_t Channel)
/**
* @brief PWM初始化
* @param 句柄
* @retval HAL_StatusTypeDef HAL状体,错误,ok,超时
*/
HAL_StatusTypeDef
HAL_TIM_PWM_Init(TIM_HandleTypeDef *htim);
HAL_TIM_PWM_Init(&htim12);
/**
* @brief 取消初始化
* @param htim : TIM handle
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_PWM_DeInit(TIM_HandleTypeDef *htim);
HAL_TIM_PWM_DeInit(&htim12);
/**
* @brief 启动PWM信号.
* @param htim : TIM handle
* @param Channel : 要用的通道
* 可以是1 -- 4
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @retval HAL status
*/
HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel) ;
HAL_TIM_PWM_Start(&htim13, TIM_CHANNEL_1);
/**
*"关闭pwm参数与开启一样"
*/
HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
HAL_TIM_PWM_Stop(&htim13, TIM_CHANNEL_1);
/**
* @brief 中断模式下PWM信号
* @param htim : TIM handle
* @param Channel :要开启的通道
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @retval HAL status
*/
"开启____start"
HAL_TIM_PWM_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
"关闭___stop"
HAL_TIM_PWM_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
/**
* @brief DMA模式下PWM信号
* @param htim : TIM handle
* @param Channel : 要开启的通道
* This parameter can be one of the following values:
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @param pData : 缓冲区
* @param Length :数据长度
* @retval HAL status
*/
"开启____start"
HAL_TIM_PWM_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length);
"关闭_____stop"
HAL_TIM_PWM_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
"重装ARR寄存器,修改重装值(计数值)"
__HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__)//
__HAL_TIM_SET_AUTORELOAD(&htim1, 1000);
"重装CCR寄存器,修改比较值(占空比)"
__HAL_TIM_SET_COMPARE(__HANDLE__, __CHANNEL__, __COMPARE__);
__HAL_TIM_SET_COMPARE(&htim1, 500);
"占空比位50%"
ADC
/**
* @:ADC使能
* @:ADC_Enable(&hadc1)
*/
ADC_Enable(ADC_HandleTypeDef* hadc);
/**
* @:ADC开启转换
* @:HAL_ADC_Start(&hadc1)
*/
HAL_ADC_Start(ADC_HandleTypeDef* hadc);
/**
* @:ADC关闭转换
* @:HAL_ADC_Stop(&hadc1)
*/
HAL_ADC_Stop(ADC_HandleTypeDef* hadc);
/**
* @:带中断的ADC转换开启
* @:HAL_ADC_Start_IT(&hadc1)
*/
HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc);
/**
* @:带中断的ADC转换停止
* @:HAL_ADC_Stop_IT(&hadc1)
*/
HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);
/**
* @:DMA方式ADC开启
* @:HAL_ADC_Start_DMA(&hadc1,Data,5)
* @:句柄,数据存储数组/指针,长度
*/
HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length);
/**
* @:DMA方式ADC关闭
* @:HAL_ADC_Stop_DMA(&hadc1,Data,5)
* @:句柄
*/
HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc);
/**
* @:获取ADC转换值
* @:HAL_ADC_GetValue(&hadc1)
*/
HAL_ADC_GetValue(ADC_HandleTypeDef* hadc);
//软件启动ADC
uint16_t Get_adc()
{
//开启ADC1
HAL_ADC_Start(&hadc1);
//等待ADC转换完成,超时为100ms
HAL_ADC_PollForConversion(&hadc1,100);
//判断ADC是否转换成功
if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1),HAL_ADC_STATE_REG_EOC))
{
//读取值
return HAL_ADC_GetValue(&hadc1);
}
return 0;
}
DAC
"初始化"
HAL_StatusTypeDef
HAL_DAC_Init(DAC_HandleTypeDef* hdac)
HAL_StatusTypeDef
HAL_DAC_DeInit(DAC_HandleTypeDef* hdac)
/**
* @brief 开启DAC转换通道
* @param hdac: 句柄
* @param Channel: 2选一
* @arg DAC_CHANNEL_1: DAC Channel1 selected
* @arg DAC_CHANNEL_2: DAC Channel2 selected
* @retval HAL status
*/
"START"
HAL_StatusTypeDef
HAL_DAC_Start(DAC_HandleTypeDef* hdac, uint32_t Channel)
HAL_DAC_Start(&dac1)
"STOP"
HAL_StatusTypeDef
HAL_DAC_Stop(DAC_HandleTypeDef* hdac, uint32_t Channel)
/**
* @brief:DMA模式转换开启
* @param:hdac 句柄 (哪个DAC)
* @param: Channel (哪个通道)
* @param: 存放数据的指针/数组
* @param: 存放的数据长度/接收5个单长度,的数据
* @param:字节对齐方式,8位有对齐,12位左,12位右
*/
"DMA-DAC-START"
__weak HAL_StatusTypeDef
HAL_DAC_Start_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t* pData, uint32_t Length, uint32_t Alignment)
"DMA-DAC-STOP"
__weak HAL_StatusTypeDef
HAL_DAC_Stop_DMA(DAC_HandleTypeDef* hdac, uint32_t Channel)
"***********""获取值"
uint32_t
HAL_DAC_GetValue(DAC_HandleTypeDef* hdac, uint32_t Channel)
"回调函数"
__weak void
HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef* hdac)
"DMA回调函数"
__weak void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef* hdac)
"error回调函数"
__weak void
HAL_DAC_ErrorCallbackCh1(DAC_HandleTypeDef *hdac)
"DAC设置函数"
HAL_StatusTypeDef
HAL_DAC_ConfigChannel(DAC_HandleTypeDef* hdac, DAC_ChannelConfTypeDef* sConfig, uint32_t Channel)
"为指定通道设定指定值"
HAL_StatusTypeDef
HAL_DAC_SetValue(DAC_HandleTypeDef* hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data)
"获取状态"
HAL_DAC_StateTypeDef
HAL_DAC_GetState(DAC_HandleTypeDef* hdac)
DMA
/**
* @brief 初始化指定DMA
* @param hdma: hdma1
* @retval HAL status
*/
"初始化"
HAL_StatusTypeDef
HAL_DMA_Init(DMA_HandleTypeDef *hdma)
"取消初始化"
HAL_StatusTypeDef
HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
/**
* @brief Start the DMA Transfer.
* @param hdma: hdma(x)
* @param SrcAddress: 自己创建的存储的地址空间
* @param DstAddress: 目标的地址
* @param DataLength: 传输的长度
* @retval HAL status
*/
"start"
HAL_StatusTypeDef
HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
"start-IT-mode"
HAL_StatusTypeDef
HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
"stop-Transfer/终止传输"
HAL_StatusTypeDef
HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
"stop--IT-Transfer/终止"
HAL_StatusTypeDef
HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
"轮询传输结束,句柄,级别,超时时间"
HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout)
"中断服务函数"
void
HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
"注册回调"
HAL_StatusTypeDef
HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma))
"取消回调"
HAL_StatusTypeDef
HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
"获取状态"
HAL_DMA_StateTypeDef
HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
CAN
/**
* @brief 初始化can
* @param hcan: 指向CAN_HandleTypeDef结构的指针,
* 该结构包含 指定CAN的配置信息
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_CAN_Init(CAN_HandleTypeDef* hcan)
/**
* @brief 配置CAN接收过滤器
* @param hcan: 指向CAN_HandleTypeDef结构的指针,
* 该结构包含 指定CAN的配置信息
* @param sFilterConfig: 指向CAN_FilterConfTypeDef结构的
* 指针,指向过滤器的配置信息
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_CAN_ConfigFilter(CAN_HandleTypeDef* hcan, CAN_FilterConfTypeDef* sFilterConfig)
/**
* @brief 取消初始化,回复默认值
* @param hcan: 指向CAN_HandleTypeDef结构的指针,
* 该结构包含 指定CAN的配置信息
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_CAN_DeInit(CAN_HandleTypeDef* hcan)
/**
* @brief 发送CAN消息
* @param hcan: 句柄
* @param Timeout: Timeout value
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_CAN_Transmit(CAN_HandleTypeDef* hcan, uint32_t Timeout)
/**
* @brief 接收
* @param hcan: 句柄
* @param FIFONumber: 指定接收FIFO编号
* @param Timeout: Timeout value
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_CAN_Receive(CAN_HandleTypeDef* hcan, uint8_t FIFONumber, uint32_t Timeout)
"中断发送"
HAL_StatusTypeDef
HAL_CAN_Transmit_IT(CAN_HandleTypeDef* hcan)
"中断接收"
HAL_StatusTypeDef
HAL_CAN_Receive_IT(CAN_HandleTypeDef* hcan, uint8_t FIFONumber)
"进入睡眠模式/低功耗模式"
HAL_StatusTypeDef
HAL_CAN_Sleep(CAN_HandleTypeDef* hcan)
"从睡眠模式中唤醒"
HAL_StatusTypeDef
HAL_CAN_WakeUp(CAN_HandleTypeDef* hcan)
/**
* @brief CAN中断请求(中断服务函数)
* @param hcan: 句柄
* @param Timeout: Timeout value
* @retval HAL status
*/
void
HAL_CAN_IRQHandler(CAN_HandleTypeDef* hcan)
"发送回调函数——自定义写逻辑"
__weak void
HAL_CAN_TxCpltCallback(CAN_HandleTypeDef* hcan)
"接收回调函数——自定义写逻辑"
__weak void
HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* hcan)
"错误回调"
__weak void
HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
"获取CAN状态"
HAL_CAN_StateTypeDef
HAL_CAN_GetState(CAN_HandleTypeDef* hcan)
IIC
"初始化"
HAL_StatusTypeDef
HAL_I2C_Init(I2C_HandleTypeDef *hi2c)
"取消初始化"
HAL_StatusTypeDef
HAL_I2C_DeInit(I2C_HandleTypeDef *hi2c)
/**
* @brief 主模式发送
* @param hi2c :hi2c(x)
* @param :目标设备地址
* @param 要发宋的数据
* @param 发送的长度
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
/**
* @brief 主模式-阻塞模式下-接收
* @param hi2c :hi2c(x)
* @param :目标设备地址
* @param 要接收的数据
* @param 接收的长度
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout)
/**
* @brief 从模式下发送
* @param hi2c :hi2c(x)
* @param 要发送的数据
* @param 接收的长度
* @param Timeout Timeout duration
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_I2C_Slave_Transmit(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout)
"从机接收"
HAL_StatusTypeDef
HAL_I2C_Slave_Receive(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size, uint32_t Timeout)
"中断模式主机发送 /句柄、设备地址、需要发送的数据、长度"
HAL_StatusTypeDef
HAL_I2C_Master_Transmit_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size)
"中断模式主机接收 /句柄、设备地址、存放接收的空间、长度"
HAL_StatusTypeDef
HAL_I2C_Master_Receive_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size)
"中断模式从机发送 /句柄、需要发送的数据、长度"
HAL_StatusTypeDef HAL_I2C_Slave_Transmit_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
"中断模式从机接收 /句柄、存放接收的空间、长度"
HAL_StatusTypeDef
HAL_I2C_Slave_Receive_IT(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
"DMA模式主机发送 /句柄、设备地址、需要发送的数据、长度"
HAL_StatusTypeDef
HAL_I2C_Master_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size)
"DMA模式主机接收 /句柄、设备地址、存放接收的空间、长度"
HAL_StatusTypeDef
HAL_I2C_Master_Receive_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size)
"DMA模式从机发送 /句柄、需要发送的数据、长度"
HAL_StatusTypeDef
HAL_I2C_Slave_Transmit_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
"DMA模式从机接收 /句柄、存放接收的空间、长度"
HAL_StatusTypeDef
HAL_I2C_Slave_Receive_DMA(I2C_HandleTypeDef *hi2c, uint8_t *pData, uint16_t Size)
"阻塞模式写入设备特定的寄存器"
"param:句柄、设备地址、设备寄存器地址、寄存器大小,要发送到数据、发送数据的大小、超时时间"
HAL_StatusTypeDef
HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
"阻塞模式读取设备特定的寄存器"
"param:句柄、设备地址、设备寄存器地址、寄存器大小,存放数据地址、大小、超时时间"
HAL_StatusTypeDef
HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
"IT模式写入设备特定的寄存器"
"param:句柄、设备地址、设备寄存器地址、寄存器大小,要发送到数据、发送数据的大小"
HAL_StatusTypeDef
HAL_I2C_Mem_Write_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
"阻塞模式读取设备特定的寄存器"
"param:句柄、设备地址、设备寄存器地址、寄存器大小,要发送到数据、发送数据的大小"
HAL_StatusTypeDef
HAL_I2C_Mem_Read_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
"DMA模式写入设备特定的寄存器"
"param:句柄、设备地址、设备寄存器地址、寄存器大小,要发送到数据、发送数据的大小"
HAL_StatusTypeDef
HAL_I2C_Mem_Write_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
"DMA模式读取设备特定的寄存器"
"param:句柄、设备地址、设备寄存器地址、寄存器大小,要发送到数据、发送数据的大小"
HAL_StatusTypeDef
HAL_I2C_Mem_Read_DMA(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size)
"检查通信设备是否准备好通信"
"句柄、设备地址、实验次数、超时时间"
HAL_StatusTypeDef
HAL_I2C_IsDeviceReady(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint32_t Trials, uint32_t Timeout)
"中断事件处理"
void
HAL_I2C_EV_IRQHandler(I2C_HandleTypeDef *hi2c)
"中断错误处理"
void
HAL_I2C_ER_IRQHandler(I2C_HandleTypeDef *hi2c)
"主机发送完成回调"
__weak void
HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
"主机接收完成回调"
__weak void
HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
"从机发送完成回调"
__weak void
HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c)
"从机接收完成回调"
__weak void
HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
"获取状态"
HAL_I2C_StateTypeDef
HAL_I2C_GetState(I2C_HandleTypeDef *hi2c)
"获取模式"
HAL_I2C_ModeTypeDef
HAL_I2C_GetMode(I2C_HandleTypeDef *hi2c)
"主机终止通信"
HAL_StatusTypeDef
HAL_I2C_Master_Abort_IT(I2C_HandleTypeDef *hi2c, uint16_t DevAddress)
SPI
"硬件SPI"
"初始化"
__weak HAL_StatusTypeDef
HAL_SPI_Init(SPI_HandleTypeDef *hspi)
"取消初始化"
HAL_StatusTypeDef
HAL_SPI_DeInit(SPI_HandleTypeDef *hspi)
/**
* @brief 阻塞模式传输一定数量的数据
* @param hspi: &hspi1
* @param pData: 需要发送的数据的指针
* @param Size: 传输数据的大小
* @param Timeout: Timeout duration
* @retval HAL status
*/
"发送"
HAL_StatusTypeDef
HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
"接收"
HAL_StatusTypeDef
HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
/**
* @brief 传送接收一体函数
* @param hspi: &hspi1
* @param pTxData: 指向发送的缓冲区的指针
* @param pRxData: 指向接收的缓冲区的指针
* @param Size: 发送和接收的数据量
* @param Timeout: Timeout duration
* @retval HAL status
*/
"发送接收一体"
HAL_StatusTypeDef
HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
"中断模式发送"
HAL_StatusTypeDef
HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
"中断模式接收"
HAL_StatusTypeDef
HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
"中断模式发送接收一体"
HAL_StatusTypeDef
HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
"DMA发送"
HAL_StatusTypeDef
HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
"DMA接收"
HAL_StatusTypeDef
HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
"DMA发送接收一体"
HAL_StatusTypeDef
HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size)
"终止传输"
HAL_StatusTypeDef
HAL_SPI_Abort(SPI_HandleTypeDef *hspi)
"DMA暂停传输"
HAL_StatusTypeDef
HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi)
"DMA回复传输"
HAL_StatusTypeDef
HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi)
"DMA停止传输"
HAL_StatusTypeDef
HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi)
"中断服务函数"
void
HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi)
"发送回调函数"
__weak void
HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
"接收回调函数"
__weak void
HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
"获取函数状态"
HAL_SPI_StateTypeDef
HAL_SPI_GetState(SPI_HandleTypeDef *hspi)
FLASH
/**
* @brief Locks the FLASH control register access
* @retval HAL Status
*/
"锁定"
HAL_StatusTypeDef
HAL_FLASH_Lock(void)
"解锁"
HAL_StatusTypeDef
HAL_FLASH_Unlock(void)
/**
* @brief 在指定地址写入
* @note 在解锁之后调用,如果锁定首先要解锁
* @note 同时请求擦除和写入,先执行擦除
* @note 新编程之前应该擦除
* @param TypeProgram:写入方式
* @param Address:要写入的地址
* @param Data:要写入的数据
* @retval HAL Status
*/
HAL_StatusTypeDef
HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
"IT-MODE"
HAL_StatusTypeDef
HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
"中断服务入口"
void
HAL_FLASH_IRQHandler(void)
RTC
"初始化"
HAL_StatusTypeDef
HAL_RTC_Init(RTC_HandleTypeDef *hrtc)
"取消初始化"
HAL_StatusTypeDef
HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc)
"设置时间(时分秒)"
"句柄,设置时间,格式(1、RTC_FORMAT_BIN\
2、RTC_FORMAT_BCD)"
HAL_StatusTypeDef
HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
"获取时间"
HAL_StatusTypeDef
HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
"设置日期(年月日)"
HAL_StatusTypeDef
HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
"获取日期"
HAL_StatusTypeDef
HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
"设置闹钟"
HAL_StatusTypeDef
HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
"中断设置闹钟"
HAL_StatusTypeDef
HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
IWDG && WWDG
***************iwdg************
"初始化看门狗"
HAL_StatusTypeDef
HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)
"刷新看门狗"
HAL_StatusTypeDef
HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
***************wwdg************
"初始化"
HAL_StatusTypeDef
HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg)
void
HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
"刷新"
HAL_StatusTypeDef
HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg);
"中断服务"
void
HAL_WWDG_IRQHandler(WWDG_HandleTypeDef *hwwdg);
TIM-定时器状态获取
typedef enum
{
HAL_TIM_STATE_RESET = 0x00U,
HAL_TIM_STATE_READY = 0x01U,
HAL_TIM_STATE_BUSY = 0x02U,
HAL_TIM_STATE_TIMEOUT = 0x03U,
HAL_TIM_STATE_ERROR = 0x04U
}HAL_TIM_StateTypeDef;
"基本状态获取"
HAL_TIM_StateTypeDef
HAL_TIM_Base_GetState(TIM_HandleTypeDef *htim)
"输出比较获取"
HAL_TIM_StateTypeDef
HAL_TIM_OC_GetState(TIM_HandleTypeDef *htim)
"PWM状态获取"
HAL_TIM_StateTypeDef HAL_TIM_PWM_GetState(TIM_HandleTypeDef *htim)
"输入捕获状态获取"
HAL_TIM_StateTypeDef
HAL_TIM_IC_GetState(TIM_HandleTypeDef *htim)
"单脉冲状态获取"
HAL_TIM_StateTypeDef HAL_TIM_OnePulse_GetState(TIM_HandleTypeDef *htim)
TIM-OutCompare/输出比较
/"##### Time Output Compare functions #####"/
/"############ 定时器输出比较功能 ##########"/
/**
* @brief 初始化定时器输出比较
* @param htim : &htim1
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_OC_Init(TIM_HandleTypeDef* htim);
/**
* @brief 取消初始化定时器输出比较
* @param htim : &htim1
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_OC_DeInit(TIM_HandleTypeDef *htim);
/**
* @brief 启动定时器输出比较
* @param htim : 句柄
* @param Channel : 通道(1-4都可选)
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_OC_Start(TIM_HandleTypeDef *htim, uint32_t Channel);
/**
* @brief 停止定时器输出比较
* @param htim : 句柄
* @param Channel : 通道(1-4都可选)
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_OC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
/**
* @brief 中断模式下启动定时器输出比较
* @param htim : 句柄
* @param Channel : 通道(1-4都可选)
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_OC_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
/**
* @brief 中断模式下停止定时器输出比较
* @param htim : 句柄
* @param Channel : 通道(1-4都可选)
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_OC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel);
/**
* @brief DMA模式下启动定时器输出比较
* @param htim : 句柄
* @param Channel : 通道(1-4都可选)
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @param pData : 原地址
* param Lengh : 数据长度
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_OC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length);
/**
* @brief DMA模式下停止定时器输出比较
* @param htim : 句柄
* @param Channel : 通道(1-4都可选)
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_OC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel);
TIMInputCapture/定时器输入捕获
/**
* @brief 初始化
* @param htim : TIM Input Capture handle
* @retval HAL status
*/
"初始化"
HAL_StatusTypeDef
HAL_TIM_IC_Init(TIM_HandleTypeDef *htim);
"取消初始化"
HAL_StatusTypeDef
HAL_TIM_IC_DeInit(TIM_HandleTypeDef *htim);
/**
* @brief 启动定时器输入捕获
* @param htim : 用哪个定时器
* @param Channel : 用哪个通道
* 四选一
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
* @arg TIM_CHANNEL_4: TIM Channel 4 selected
* @retval HAL status
*/
"*****START******"
HAL_StatusTypeDef
HAL_TIM_IC_Start (TIM_HandleTypeDef *htim, uint32_t Channel);
"*****STOP******"
HAL_StatusTypeDef
HAL_TIM_IC_Stop(TIM_HandleTypeDef *htim, uint32_t Channel);
"中断模式启动"
HAL_StatusTypeDef
HAL_TIM_IC_Start_IT (TIM_HandleTypeDef *htim, uint32_t Channel)
"中断模式关闭"
HAL_StatusTypeDef
HAL_TIM_IC_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
"DMA_MODE_START"
HAL_StatusTypeDef
HAL_TIM_IC_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length)
"DMA_MODE_STOP"
HAL_StatusTypeDef
HAL_TIM_IC_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
TimOnePulse/定时器单脉冲
"初始化"
HAL_StatusTypeDef
HAL_TIM_OnePulse_Init(TIM_HandleTypeDef *htim, uint32_t OnePulseMode)
"取消初始化"
HAL_StatusTypeDef
HAL_TIM_OnePulse_DeInit(TIM_HandleTypeDef *htim)
/**
* @brief 启动
* @param htim : TIM One Pulse handle
* @param OutputChannel : TIM Channels to be enabled
* 2选1,支持单脉冲的通道少
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
* @retval HAL status
*/
HAL_StatusTypeDef
HAL_TIM_OnePulse_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
"参数同上_stop"
HAL_StatusTypeDef
HAL_TIM_OnePulse_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
"interrupt-mode-start"
HAL_StatusTypeDef HAL_TIM_OnePulse_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
"interrupt-mode-stop"
HAL_StatusTypeDef HAL_TIM_OnePulse_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
"DMA-MODE-START"
"!!!!!!!!!!!!!!不支持DMA!!!!!!!!!!!!"
全局中断开启关闭,软系统复位
__disable_irq(); //关闭全局中断
/
__enable_irq(); //开启全局中断
/
NVIC_SystemReset() //软复位系统,最好关闭中断使用
CAN
把逻辑信号转换为差分信号
如同串口中的MAX3232用作电*转换,CAN收发器的作用则是把逻辑信号转换为差分信号。 CAN总线采用差分信号传输,通常情况下只需要两根信号线就可以进行正常的通信。 在差分信号中,逻辑0和逻辑1是用两根差分信号线的电压差来表示。
微机原理
ARM中FLASH和RAM、ROM的区别
只读存储器(Read Only Memory,ROM)。ROM所存数据,一般是装入整机前事先写好的,整机工作过程中只能读出,而不像随机存储器那样能快速地、方便地加以改写。ROM所存数据稳定,计算机中的ROM主要是用来存储一些系统信息,或者启动程序BIOS程序,这些都是非常重要的,只可以读一般不能修改,断电也不会消失。
随机存取存储器(Random Access Memory,RAM)又称作“随机存储器”,是与CPU直接交换数据的内部存储器,也叫主存(内存)。它可以随时读写,而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储媒介。当电源关闭时RAM不能保留数据。如果需要保存数据,就必须把它们写入一个长期的存储设备中(例如硬盘)。RAM和ROM相比,两者的最大区别是RAM在断电以后保存在上面的数据会自动消失,而ROM不会自动消失,可以长时间断电保存。
从电脑来说一般比较好理解,RAM就是我们*时所说的运行内存,它的确是随时可读写的。因为CPU处理的数据都是以运行内存为中介的。断电后信息是不保存的。那么对于ROM来说,是不是就是硬盘呢?不是说ROM只可以读吗?硬盘却是可以修改的。的确,必须明确一点,RAM与ROM都是内存,而硬盘是外存,所以ROM不等于硬盘。只不过RAM叫随机内存,ROM叫只读内存。
计算机基础 位 字节 字 字长
位、字节、字、KB、MB
位:“位(bit)”是电子计算机中最小的数据单位。每一位的状态只能是0或1。
字节:8个二进制位构成1个“字节(Byte)”,它是存储空间的基本计量单位。1个字节可以储存1个英文字母或者半个汉字,换句话说:1个汉字占据2个字节的存储空间。
字:“字”由若干个字节构成,字的位数叫做字长,不同档次的机器有不同的字长。例如一台8位机,它的1个字就等于1个字节,字长为8位。如果是一台16位机,那么,它的1个字就由2个字节构成,字长为16位。字是计算机进行数据处理和运算的单位。
KB:K表示1024,也就是2的10次方。1KB表示1K个Byte,也就是1024个字节。
MB:1MB = 220 Bytes = 1048576Bytes
在计算机/通讯行业中,计算数据传送速度使用每秒传送公制数据量来计
• 1 bit (b) = 0 or 1 = one binary digit 一个二进制位元
• 1 kilobit(kb)=10 e3 bits = 1,000 bits 一千位元
• 1 Megabit(Mb)=10 e6 bits = 1,000,000 bits 一百万位元
• 1 Gigabit(Gb)=10 e9 bits = 1,000,000,000 bits 一万亿位元
在我们常说的56K拨号,100M局域网都是bps计量,当用于软件下载时,下载工具一般又以Bps计算,所以它们之间有 8 bit=1 Byte 的换算关系,那么56Kbps拨号极限下载速度是 56Kbps/8=7KBps 每秒下载7K字节。
在数据存储,容量计算中,一般又结合公制的进制和二进制的数据计算方法来计算,
(二进制)
• 1 byte (B) = 8 bits (b) 字节=8个二进制位
• 1 Kilobyte(K/KB)=2 e10bytes=1,024 bytes 千字节
• 1 Megabyte(M/MB)=2 e20bytes=1,048,576 bytes 兆字节
• 1 Gigabyte(G/GB)=2 e30bytes=1,073,741,824 bytes 千兆字节
• 1 Terabyte(T/TB)=2 e40bytes=1,099,511,627,776 bytes吉字节
一些存储器厂家特别是硬盘厂家就更紧密结合十进制来计算,这就是为什么操作系统显示的容量与厂家标示的容量有一些差异的原因
(十进制)
• 1 byte(B) = 8 bits (b)
• 1 Kilobyte(K/KB) = 10 e3bytes = 1,000 bytes
• 1 Megabyte (M/MB) = 10 e6bytes = 1,000,000 bytes
• 1 Gigabyte (G/GB) = 10 e9bytes = 1,000,000,000 bytes
• 1 Terabyte (T/TB) = 10 e12bytes = 1,000,000,000,000 bytes
寄存器小技巧
一些给寄存器赋值的小技巧。
通常我们只想修改32bit中的某一位,清零或者置1
GPIOA->CRL |= 1<<6; 将bit6设为1
GPIOA->CRL |= (1<<6+1<<7);GPIOA->CRL |= (0x3<<6); 将bit6和7设为1
GPIOA->CRL &= ~(1<<6); 将bit6清零
GPIOA->CRL &= ~(1<<6+1<<7);GPIOA->CRL &= ~(0x3<<6); 将bit6和7清零
数据高低位 :左高右低
协议
I2C
1 I2C总线物理拓扑结构

I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电*时序的控制,来产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电*。
I2C通信方式为半双工,只有一根SDA线,同一时间只可以单向通信,485也为半双工,SPI和uart为双工。
2 I2C总线特征
I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址(地址通过物理接地或者拉高,可以从I2C器件的数据手册得知,如TVP5158芯片,7位地址依次bit6~bit0:x101 1xxx, 最低三位可配,如果全部物理接地,则该设备地址为0x58, 而之所以7bit因为1个bit要代表方向,主向从和从向主),主从设备之间就通过这个地址来确定与哪个器件进行通信,在通常的应用中,我们把CPU带I2C总线接口的模块作为主设备,把挂接在总线上的其他设备都作为从设备。
I2C总线上可挂接的设备数量受总线的最大电容400pF 限制,如果所挂接的是相同型号的器件,则还受器件地址位的限制。
I2C总线数据传输速率在标准模式下可达100kbit/s,快速模式下可达400kbit/s,高速模式下可达3.4Mbit/s。一般通过I2C总线接口可编程时钟来实现传输速率的调整,同时也跟所接的上拉电阻的阻值有关。
I2C总线上的主设备与从设备之间以字节(8位)为单位进行双向的数据传输。
3 I2C总线协议
I2C协议规定,总线上数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。起始和结束信号总是由主设备产生(意味着从设备不可以主动通信?所有的通信都是主设备发起的,主可以发出询问的command,然后等待从设备的通信)。
起始和结束信号产生条件:总线在空闲状态时,SCL和SDA都保持着高电*,当SCL为高电*而SDA由高到低的跳变,表示产生一个起始条件;当SCL为高而SDA由低到高的跳变,表示产生一个停止条件。
在起始条件产生后,总线处于忙状态,由本次数据传输的主从设备独占,其他I2C器件无法访问总线;而在停止条件产生后,本次数据传输的主从设备将释放总线,总线再次处于空闲状态。起始和结束如图所示:

在了解起始条件和停止条件后,我们再来看看在这个过程中数据的传输是如何进行的。前面我们已经提到过,数据传输以字节为单位。主设备在SCL线上产生每个时钟脉冲的过程中将在SDA线上传输一个数据位,当一个字节按数据位从高位到低位的顺序传输完后,紧接着从设备将拉低SDA线,回传给主设备一个应答位, 此时才认为一个字节真正的被传输完成。当然,并不是所有的字节传输都必须有一个应答位,比如:当从设备不能再接收主设备发送的数据时,从设备将回传一个否 定应答位。数据传输的过程如图所示:

在前面我们还提到过,I2C总线上的每一个设备都对应一个唯一的地址,主从设备之间的数据传输是建立在地址的基础上,也就是说,主设备在传输有效数据之前要先指定从设备的地址,地址指定的过程和上面数据传输的过程一样,只不过大多数从设备的地址是7位的,然后协议规定再给地址添加一个最低位用来表示接下来数据传输的方向,0表示主设备向从设备写数据,1表示主设备向从设备读数据。向指定设备发送数据的格式如图所示:(每一最小包数据由9bit组成,8bit内容+1bit ACK, 如果是地址数据,则8bit包含1bit方向)

下图是完整的一帧I2C数据:

4 I2C总线操作
对I2C总线的操作实际就是主从设备之间的读写操作。大致可分为以下三种操作情况:
- 主设备往从设备中写数据。数据传输格式如下:(数据包括从机寄存器地址和需要写入寄存器的数据data)

- 主设备从从设备中读数据。数据传输格式如下:(???这个有误)

- 主设备往从设备中写数据,然后重启起始条件,紧接着从从设备中读取数据;或者是主设备从从设备中读数据,然后重启起始条件,紧接着主设备往从设备中写数据。数据传输格式如下:

第三种操作在单个主设备系统中,重复的开启起始条件机制要比用STOP终止传输后又再次开启总线更有效率。
I2C HAL库函数
HAL_I2C_Master_Transmit
比较Mem函数来看,这个函数更倾向于写指令,而Mem函数更适合在寄存器的内存里写大量数据,比如OLED。
HAL_I2C_Mem_Write
功能:在阻塞模式下将大量数据写入特定的内存地址
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
参数:
1、I2C指针,即用I2C1 还是 I2C2…
2、器件地址uint16_t DevAddress
3、要写入的内存地址 uint16_t MemAddress
4、内存地址类型,是一个地址存8bit ,还是16bit数据 , uint16_t MemAddSize I2C_MEMADD_SIZE_8BIT
5、要写入的数组指针uint8_t *pData
6、数据 大小
7、多少时间没完成定义为超时
SPI
基本概念
全称Serial Peripheral Interface,是一种全双工的,同步通信
物理层
共四条线:MOSI、MISO、SCK、NSS
| 信号线 | 作用 |
|---|---|
| MOSI | 主机输出,从机输入 |
| MISO | 主机输入,从机输出 |
| SCK | 时钟信号,由主机产生,用于通讯同步 |
| NSS | 从机使能信号,由主机控制(片选线) |
协议层
通讯的起始和停止
通讯起始:NSS线信号由高变低,对应的从机被选中,开始通讯
通讯结束:NSS线信号由低变高,对应的从机取消选中状态
SPI的四种模式
四种模式的区别:总线空闲时sck的时钟状态(CPOL)及数据采样时刻(CPHA)。
CPOL:SPI通讯设备处于空闲时(NSS为高电*时)SCK的状态。CPOL=0,则SCK线在空闲时为低电*;CPOL=1,则SCK线在空闲时为高电*
CPHA:数据采样的时刻。CPHA=0,MOSI或MISO线上的信号将在SCK线的奇数个跳变沿被采样;CPHA=1,MOSI或MISO线上的信号在SCK线的偶数个个跳变沿被采样。

注:四种模式都可以使用,但是主从设备必须采用同一种模式。
CubeMX配置
-
左侧目录>Connectivity>点SPI1/SPI2……~> 勾选模式
-

-
-
参数配置

编程
HAL库关于CAN的所有函数定义和结构体分别在 Drivers/STM32F4xx_HAL_Driver 文件夹下 stm32f4xx_HAL_Driver.c 和 stm32f4xx_HAL_Driver.h 中
下面列举一些基本的和常用的
结构体
只有SPI_InitTypeDef和SPI_HandleTypeDef,分别用于初始化定义和句柄定义。如果配合CubeMx,这两个都用不上
函数
SPI关于IO的定义在stm32f4xx_HAL_Driver.c文件中701-2563行
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
功能:发送一段数据
参数:spi句柄指针发送数据数组名
发送数组长度
timeout,超出这个时间就报错,单位是ms
返回值:返回值:HAL状态
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
功能:接收一段数据
参数:spi句柄指针接收数据数组名
接收数组长度
timeout,超出这个时间就报错,单位是ms
返回值:返回值:HAL状态
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, uint8_t *pTxData, uint8_t *pRxData, uint16_t Size,uint32_t Timeout)
功能:接收并发送一段数据
参数:spi句柄指针发送数据数组名
接收数据数组名
接收发送数组长度
timeout,超出这个时间就报错,单位是ms
返回值:返回值:HAL状态
编程实例
SPI 的编程较CAN来说方便了很多,配合Cubemx的话就不需要做初始化配置了。
然而由于实际使用过程中所使用的STM可能作为上位机也可能作为下位机,也就是主机和从机。作为从机,相当于一个部门的下属,只需要管输入输出就完事了,不需要操心片选的事。作为主机就需要协调各从机了,相当于一个部门的主管,需要给下级授意,它改接收任务或者给主机汇报
CS(片选信号)有硬件片选和软件片选两种形式。硬件片选是单片机在收发消息时自动进行了片选线拉低并抬高的步骤,软件片选则需要在每次收发前将片选线拉低,通讯结束再将片选线拉高。
硬件片选
硬件片选是硬件已经封装好了通讯时序和片选信号开始终止,所以只需要调用上述的IO类函数即可
软件片选
软件片选稍微麻烦一点。需要另外分一个单片机引脚给CS信号,GPIO输出功能,最好配置为上拉。
当需要和某从机通信时,需要给它发送片选命令,即手动将片选线的高电*置低。例如下面这个给从机的发送过程:
HAL_GPIO_WritePin(GPIOx, GPIO_PIN_x, GPIO_PIN_RESET) //将片选线置低,告诉从机开始通信 HAL_SPI_Tramsmit(&hspix, (uint8_t*)data, len, timeout) //发送一个数据 HAL_GPIO_WritePin(GPIOx, GPIO_PIN_x, GPIO_PIN_SET) //将片选线重新置高,告诉从机结束通信
DMA
DMA的基本介绍
什么是DMA (DMA的基本定义)
DMA,全称Direct Memory Access,即直接存储器访问。
DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。
我们知道CPU有转移数据、计算、控制程序转移等很多功能,系统运作的核心就是CPU,
CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,是不是能够更好的利用CPU的资源呢?
因此:转移数据(尤其是转移大量数据)是可以不需要CPU参与。比如希望外设A的数据拷贝到外设B,只要给两种外设提供一条数据通路,直接让数据由A拷贝到B 不经过CPU的处理,

DMA就是基于以上设想设计的,它的作用就是解决大量数据转移过度消耗CPU资源的问题。有了DMA使CPU更专注于更加实用的操作–计算、控制等。
DMA定义:
DMA用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU的干预,通过DMA数据可以快速地移动。这就节省了CPU的资源来做其他操作。
DMA传输方式
DMA的作用就是实现数据的直接传输,而去掉了传统数据传输需要CPU寄存器参与的环节,主要涉及四种情况的数据传输,但本质上是一样的,都是从内存的某一区域传输到内存的另一区域(外设的数据寄存器本质上就是内存的一个存储单元)。四种情况的数据传输如下:
- 外设到内存
- 内存到外设
- 内存到内存
- 外设到外设
DMA传输参数
我们知道,数据传输,首先需要的是
1 数据的源地址
2 数据传输位置的目标地址
3 传递数据多少的数据传输量
4 进行多少次传输的传输模式
DMA所需要的核心参数,便是这四个
当用户将参数设置好,主要涉及源地址、目标地址、传输数据量这三个,DMA控制器就会启动数据传输,当剩余传输数据量为0时 达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式 当到达传输终点时会重新启动DMA传输。
也就是说只要剩余传输数据量不是0,而且DMA是启动状态,那么就会发生数据传输。

DMA的主要特征
每个通道都直接连接专用的硬件DMA请求,每个通道都同样支持软件触发。这些功能通过软件来配置;
- 在同一个DMA模块上,多个请求间的优先权可以通过软件编程设置(共有四级:很高、高、中等和低),优先权设置相等时由硬件决定(请求0优先于请求1,依此类推);
- 独立数据源和目标数据区的传输宽度(字节、半字、全字),模拟打包和拆包的过程。源和目标地址必须按数据传输宽度对齐;
- 支持循环的缓冲器管理;
- 每个通道都有3个事件标志(DMA半传输、DMA传输完成和DMA传输出错),这3个事件标志逻辑或成为一个单独的中断请求;
- 存储器和存储器间的传输、外设和存储器、存储器和外设之间的传输;
- 闪存、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标;
- 可编程的数据传输数目:最大为65535。
DMA CubeMX配置

- 点击DMASettings 点击 Add 添加通道
- 选择USART_RX USART_TX 传输速率设置为中速
- DMA传输模式为正常模式
- DMA内存地址自增,每次增加一个Byte(字节)
右侧点击System Core 点击DMA

DMA Request : DMA传输的对应外设
注意: 如果你是在DMA设置界面添加DMA 而没有开启对应外设的话 ,默认为MENTOMEN
Channel DMA传输通道设置
DMA1 : DMA1 Channel 0~DMA1 Channel 7
DMA2: DMA2 Channel 1~DMA1 Channel 5
Dirction : DMA传输方向
四种传输方向:
外设到内存 Peripheral To Memory
内存到外设 Memory To Peripheral
内存到内存 Memory To Memory
外设到外设 Peripheral To Peripheral
Priority: 传输速度
最高优先级 Very Hight
高优先级 Hight
中等优先级 Medium
低优先级;Low
DMA传输模式

Normal:正常模式
当一次DMA数据传输完后,停止DMA传送 ,也就是只传输一次
Circular: 循环模式
传输完成后又重新开始继续传输,不断循环永不停止
DMA指针递增设置

Increment Address:地址指针递增(上方有介绍)。
左侧Src Memory 表示外设地址寄存器
功能:设置传输数据的时候外设地址是不变还是递增。如果设置 为递增,那么下一次传输的时候地址加 Data Width个字节,
右侧Dst Memory 表示内存地址寄存器
功能:设置传输数据时候内存地址是否递增。如果设置 为递增,那么下一次传输的时候地址加 Data Width个字节,
这个Src Memory一样,只不过针对的是内存。
INA226
功能
可以高低边,检测电流,电压,功率,通过I2c读取寄存器
功能配置
可以通过配置寄存器,来确定采样时间等,详见[ina226.pdf](file:///C:/Users/ljq10/Desktop/电赛/冬令营课件/Day4_I2C_226/ina226.pdf)
引脚功能
- ALT:如果被拉低,则发生错误,等于报警
- VCC:2.7-5.5 V
Register Map
见 ina226.pdf P21
[ina226.pdf](file:///C:/Users/ljq10/Desktop/电赛/冬令营课件/Day4_I2C_226/ina226.pdf)
注意事项
- Vbus最大电压36V
- 高边采样 Vbus链接Vs-
- 底边采样 ,需要程序补偿导线和电阻的分压
- 当需要校准的时候,可以把校准系数计算出来写入校准寄存器
- 可以调用GItHub的库 详见2023电赛培训4.INA226_I2C_哔哩哔哩_bilibili视频后面二十分钟
串口
printf重定向
1.头文件调用<stdio.h>
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
收发函数使用
接收中断
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart->Instance==USART1)
{
if(eg_[0]==0xFF)
{
yy(y1);
}
else
{
yy(y2);
}
}
HAL_UART_Receive_IT(&huart1,eg_,sizeof(eg_));//清除标志位
}
cubeMX配置
无需配置,出了波特率。
DMA串口
配置好DMA,数据宽度为 bit。
#define UART1_printf_DMA(...) HAL_UART_Transmit_DMA(&huart2,\
(uint8_t *)u_buf,\
sprintf((char*)u_buf,__VA_ARGS__))
uint8_t u_buf[256];
中断
时钟中断
HAL_TIM_Base_Start_IT(&htim3);//使能TIM3 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)//中断回调函数 { if (htim->Instance == TIM3) { } }
按键中断
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if(GPIO_Pin == GPIO_PIN_2) { } if(GPIO_Pin == GPIO_PIN_3) { } }绝不可以在中断里写延时
延时——us

#define DLY_TIM_Handle (&htim4)
void delay_us(uint16_t nus)
{
__HAL_TIM_SET_COUNTER(DLY_TIM_Handle, 0);
__HAL_TIM_ENABLE(DLY_TIM_Handle);
while (__HAL_TIM_GET_COUNTER(DLY_TIM_Handle) < nus)
{
}
__HAL_TIM_DISABLE(DLY_TIM_Handle);
}
C语言
写库函数的规则
头文件
注意事项
- 浮点数要带上 f。
MSP432
GPIO
GPIO输出
GPIO输入
Time_A时钟CS(clock system)
时钟源介绍
电赛就用外部高速晶振 48MHz
时钟初始化设置
void CS_setExternalClockSourceFrequency(uint32_t lfxt_XT_CLK_frequency,
uint32_t hfxt_XT_CLK_frequency);
//设置外部晶振LFXT和HFXT的频率值
CS_setExternalClockSourceFrequency(CS_32MHZ,CS_48MHZ);
--------------------------------------------------------------------------------
void CS_setReferenceOscillatorFrequency(uint8_t referenceFrequency);
//选择REFO时钟源频率
//! \param referenceFrequency selects between the valid frequencies:
//! - \b CS_REFO_32KHZ,
//! - \b CS_REFO_128KHZ,
--------------------------------------------------------------------------------
uint32_t CS_getACLK(void);
uint32_t CS_getSMCLK(void);
uint32_t CS_getMCLK(void);
uint32_t CS_getBCLK(void);
uint32_t CS_getHSMCLK(void);
uint32_t CS_getDCOFrequency(void);
//获取各时钟源频率
//单位为Hz
--------------------------------------------------------------------------------
GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0);//设置P1.0为输出模式
GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2,GPIO_PIN6,GPIO_PRIMARY_MODULE_FUNCTION);//引脚复用为PWM模式
GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P7,GPIO_PIN4,GPIO_PRIMARY_MODULE_FUNCTION);//引脚复用为PWM模式
Timer_A_PWMConfig PWM1;//配置PWM1结构体
Timer_A_PWMConfig PWM2;//配置PWM2结构体
PWM1.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //时钟源
PWM1.clockSourceDivider = 1; //1分频
PWM1.timerPeriod = 1199; //4o KHz
PWM1.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_3;//通道0
PWM1.compareOutputMode = TIMER_A_OUTPUTMODE_TOGGLE_SET;//输出模式
PWM1.dutyCycle = 599; //占空比50
PWM2.clockSource = TIMER_A_CLOCKSOURCE_SMCLK; //时钟源
PWM2.clockSourceDivider = 48; //1分频
PWM2.timerPeriod = 19999; //50 Hz
PWM2.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_4;//通道0
PWM2.compareOutputMode = TIMER_A_OUTPUTMODE_TOGGLE_SET;//输出模式
PWM2.dutyCycle = 9999; //占空比50
Timer_A_generatePWM(TIMER_A0_BASE,&PWM1);//TA0.3 == P2.6
Timer_A_generatePWM(TIMER_A1_BASE,&PWM2);//TA1.4 == P7.4
音频传输协议 I2S
38.1 I2S简介
Inter-IC Sount Bus(I2S)是飞利浦半导体公司(现为恩智浦半导体公司)针对数字音频设备之间的音频数据传输而制定的一种总线标准。在飞利浦公司的I2S标准中,既规定了硬件接口规范,也规定了数字音频数据的格式。
38.1.1 数字音频技术
现实生活中的声音是通过一定介质传播的连续的波,它可以由周期和振幅两个重要指标描述。正常人可以听到的声音频率范围为20Hz~20KHz。现实存在的声音是模拟量,这对声音保存和长距离传输造成很大的困难,一般的做法是把模拟量转成对应的数字量保存,在需要还原声音的地方再把数字量的转成模拟量输出,参考图 381。

图 381 音频转换过程
模拟量转成数字量过程,一般可以分为三个过程,分别为采样、量化、编码,参考图 382。用一个比源声音频率高的采样信号去量化源声音,记录每个采样点的值,最后如果把所有采样点数值连接起来与源声音曲线是互相吻合的,只是它不是连续的。在图中两条蓝色虚线距离就是采样信号的周期,即对应一个采样频率(FS),可以想象得到采样频率越高最后得到的结果就与源声音越吻合,但此时采样数据量越越大,一般使用44.1KHz采样频率即可得到高保真的声音。每条蓝色虚线长度决定着该时刻源声音的量化值,该量化值有另外一个概念与之挂钩,就是量化位数。量化位数表示每个采样点用多少位表示数据范围,常用有16bit、24bit或32bit,位数越高最后还原得到的音质越好,数据量也会越大。

图 382 声音数字化过程
38.1.2 I2S总线接口
I2S总线接口有3个主要信号,但只能实现数据半双工传输,后来为实现全双工传输有些设备增加了扩展数据引脚。STM32f42x系列控制器支持扩展的I2S总线接口。
(1) SD(Serial Data):串行数据线,用于发送或接收两个时分复用的数据通道上的数据(仅半双工模式),如果是全双工模式,该信号仅用于发送数据。
(2) WS(Word Select):字段选择线,也称帧时钟(LRC)线,表明当前传输数据的声道,不同标准有不同的定义。WS线的频率等于采样频率(FS)。
(3) CK(Serial Clock):串行时钟线,也称位时钟(BCLK),数字音频的每一位数据都对应有一个CK脉冲,它的频率为:2采样频率量化位数,2代表左右两个通道数据。
(4) ext_SD(extend Serial Data):扩展串行数据线,用于全双工传输的数据接收。
另外,有时为使系统间更好地同步,还要传输一个主时钟(MCK),STM32F42x系列控制器固定输出为256* FS。
38.1.3 音频数据传输协议标准
随着技术的发展,在统一的I2S硬件接口下,出现了多种不同的数据格式,可分为左对齐(MSB)标准、右对齐(LSB)标准、I2S Philips标准。另外,STM32F42x系列控制器还支持PCM(脉冲编码调)音频传输协议。下面以STM32F42x系列控制器资源解释这四个传输协议。
STM32f42x系列控制器I2S的数据寄存器只有16bit,并且左右声道数据一般是紧邻传输,为正确得到左右两个声道数据,需要软件控制数据对应通道数据写入或读取。另外,音频数据的量化位数可能不同,控制器支持16bit、24bit和32bit三种数据长度,因为数据寄存器是16bit的,所以对于24bit和32bit数据长度需要发送两个。为此,可以产生四种数据和帧格式组合:
将16位数据封装在16位帧中
将16位数据封装在32位帧中
将24位数据封装在32位帧中
将32位数据封装在32位帧中
当使用32位数据包中的16位数据时,前16位(MSB)为有效位,16位LSB被强制清零,无需任何软件操作或DMA请求(只需一个读/写操作)。如果程序使用DMA传输(一般都会用),则24位和32位数据帧需要对数据寄存器执行两次DMA操作。24位的数据帧,硬件会将8位非有效位扩展到带有0位的32位。对于所有数据格式和通信标准而言,始终会先发送最高有效位(MSB优先)。
1. I2S Philips标准
使用WS信号来指示当前正在发送的数据所属的通道,为0时表示左通道数据。该信号从当前通道数据的第一个位(MSB)之前的一个时钟开始有效。发送方在时钟信号(CK)的下降沿改变数据,接收方在上升沿读取数据。WS信号也在SCK的下降沿变化。参考图 383,为24bit数据封装在32bit帧传输波形。正如之前所说,WS线频率对于采样频率FS,一个WS线周期包括发送左声道和右声道数据,在图中实际需要64个CK周期来完成一次传输。

图 383 I2S Philips标准24bit传输
2. 左对齐标准
在WS发生翻转同时开始传输数据,参考图 384,为24bit数据封装在32bit帧传输波形。该标准较少使用。注意此时WS为1时,传输的是左声道数据,这刚好与I2S Philips标准相反。

图 384 左对齐标准24bit传输
3. 右对齐标准
与左对齐标准类似,参考图 385,为24bit数据封装在32bit帧传输波形。

图 385 右对齐标准24bit传输
4. PCM标准
PCM即脉冲编码调制,模拟语音信号经过采样量化以及一定数据排列就是PCM了。WS不再作为声道数据选择。它有两种模式,短帧模式和长帧模式,以WS信号高电*保持时间为判别依据,长帧模式保持13个CK周期,短帧模式只保持1个CK周期,可以通过相关寄存器位选择。如果有多通道数据是在一个WS周期内传输完成的,传完左声道数据就紧跟发送右声道数据。图 386为单声道数据16bit扩展到32bit数据帧发送波形。

图 386 PCM标准16bit传输
I2S Cube 配置


I2S代码
/* USER CODE BEGIN PV */
uint32_t dma[4];
uint32_t val24;
int val32;
/* USER CODE END PV */
//开始DMA传输
HAL_I2S_Receive_DMA(&hi2s2,(uint16_t*)dma,4);
//I2S接收完成回调函数
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
{
if(hi2s==&hi2s1){
cb_cnt++;//回调次数计数
//将两个32整型合并为一个
//dat32 example: 0000fffb 00004f00
val24=(dma[0]<<8)+(dma[1]>>8);
//将24位有符号整型扩展到32位
if(val24 & 0x800000){//negative
val32=0xff000000 | val24;
}else{//positive
val32=val24;
}
//以采样频率的十分之一,串口发送采样值
if(cb_cnt%10==0)
printf("V=%d\r\n",val32);
}
}
