一、看门狗
①解决了永远不复位的情况,如果成功减到0(就是程序跑飞卡死)就会复位;
②实现“看门”过程:启动–在键值寄存器(IWDG_KR)写入0XCCCC; 大部分时间–计数器开始从 0xFFF 递减计数,到末尾 0x000 时,会产生一个复位信号(IWDG_RESET);结束–往键寄存器 IWDG_KR 中被写入 0xAAAA;
③独立看门狗:由专用的低速时钟驱动,即使主时钟发生故障它仍然有效,对时间精度要求低。窗口看门狗:从APB1时钟分频后得到时钟驱动,对时间要求精度高。
二、定时器中断:
①定时器有定时中断和外部时钟:中断直接IRQhander即可,时钟的要在while里面计数累计
STM32F103系列定时器通道对应IO汇总:
https://blog.csdn.net/KevinYT/article/details/124669022
103VE定时器映射表:各种功能都能用这些定时器去实现,所以是通用
②
定时器中断配置的一般步骤:
1)TIM3 时钟使能。TIM3 是挂载在 APB1 之下,所以我们通过 APB1 总线下的使能使能函数来使能 TIM3。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
2)初始化定时器参数,设置自动重装值,分频系数,计数方式等。
voidTIM_TimeBaseInit(TIM_TypeDef*TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
第一个参数是确定是哪个定时器,这个比较容易理解。第二个参数是定时器初始化参数结 构体指针,结构体类型为 TIM_TimeBaseInitTypeDef。
3)设置 TIM3_DIER 允许更新中断,也就是允许去做别的一些新的事情。
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
其中第二个参数非常关键,是用来指明我们使能的定时器中断的类型,定时器中断的类型有很 多种,包括更新中断 TIM_IT_Update,触发中断 TIM_IT_Trigger,以及输入捕获中断等等。可配置如下TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
4)TIM3 中断优先级设置。
5)允许 TIM3 工作,也就是使能 TIM3。
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
总的来说:
配置此TIM3_Int_Init()时,需要先将RCC使能,然后设置TIM3初始化的参数,然后使能指定的TIM3中断,仅仅是中断,随后设置中断优先级,最后使能TIMx:TIM_Cmd(TIM3, ENABLE);
③PWM,假如自动重装载值为100,若计数在0—50之间则在相应的通道输出为低电平,在50—100之间为高电平,这样就能产生一种波形脉冲。若要调整波形的占空比,则需要调整50。而若要调节频率,则需要调整100.高电平时间越久,转的越快。
④◆分频的话:
Tout= ((arr+1)*(psc+1))/Tclk公式理解汇总:
Tout= ((arr+1)*(psc+1))/Tclk:
其中arr为你重装的值,psc是预分频计时器的值,Tclk是时钟频率,(psc+1))/Tclk*1是计算的计数器 减少/增加 一个数所用的时间;那么(psc+1))/Tclk*(arr+1)就是一次定时器的时间:然后继续重装arr再次计数,计时:就构成一个循环;
举例:
Tout= ((arr+1)(psc+1))/Tclk;就可以了,比如Tout=(4999+1)(7199+1)/72000000=0.5s,也就是说你的中断时间为0.5s.
◆不分频的话(就像Pwm):
TIM3_PWM_Init(899,0); //不分频。PWM频率=72000000/900=80Khz
⑤自敲经验:
1.在写RCC的定时器时钟时,RCC_APB1PeriphClockCmd()这个括号里面需要写出
RCC_APB1Periph_TIM3要在有效格式中cv.不要自己臆测。
2.在.h的文件中的TIM3_Int_Init()函数中的括号需要填写入口参数才能让程序追溯到其值,按下:
void TIM3_Int_Init(u16 arr,u16 psc);
3.下面这个被定义的函数的第二个变量有点长,是取自己赋予名字的变量的地址,而不是原本就有定的名字。
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct
4.用定时器的优势之处,定时器是硬件定时,而不用软件多次进入中断,打扰主程序的执行。
TIP:
TIM2_CH1_ETR:在使用定时器的时候,在引脚复用功能中看到了TIM2_CH1_ETR,这个ETR是什么意思呢?
答:TIM2_CH1_ETR表示两个功能选一个,分别是TIM2_CH1和TIM2_ETR,TIM2_CH1表示让这个引脚作为TIM2的第一通道对应引脚;TIM2_ETR表示让这个引脚作为TIM2外部时钟提供引脚,这种功能有两种模式,如下图:
5.NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
//设置NVIC中断分组2:2位抢占优先级,2位响应优先级;为什么设置NVIC中断分组2:2位抢占优先级:抢占和响应都一样的时候,看哪个中断先发生就先执行。
比如有A和B,分组设置为2(即为2位抢占优先级,2位响应优先级),A的SCB中IP bit为1011,B的SCB中IP bit为1001,A抢占为10,B抢占也为10,此时A、B抢占优先级一样,
如果随便更改分组,比如分组3,A抢占就是101,B抢占就是100,那么B优先级就大于A了。
三、SPI:
①SPI:概念:一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚。
从图中可以看出,主机和从机都有一个串行移位寄存器,主机通过向它的 SPI 串行寄存器
写入一个字节来发起一次传输。寄存器通过 MOSI 信号线将字节传送给从机,从机也将自己的
移位寄存器中的内容通过 MISO 信号线返回给主机。这样,两个移位寄存器中的内容就被交换。
外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,
若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。
②如果要加入库函数里面原来的外设,那就不止是....conf.h里面要把注释去掉,还要在总文件里面加入:
③实际开发:
●未改动前的波形:
●改动后的波形:
改动后:16位的数据分两次读取,先读进来的是低八位,然后移位到高位然后再读取高八位。同时为了让spi的时钟线稳定,都会在操作时钟线后延时1us
参考–https://blog.csdn.net/qq_27508477/article/details/83117005
●再改进:如果是数据不对,没有读到高八位,然后又重新有MISO再上升,那就是数据处理有问题,所以就由temp=MAX6675_Read_Temp_Bit(0xFF);//HSB
改成或上:
temp|=MAX6675_Read_Temp_Bit(0xFF);//HSB,数据处理的问题:要或上,不然每次都覆盖掉上一次低位读取的温度,那么就数据当然不对
OK了:
四、ADC:
①STM32 的 ADC 是 12 位逐次逼近型的数字转换模拟器。
它有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫
描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。 模拟看
门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。
对照自编写的那个ADC为啥不行的原因:
②DAC可以形成波形,正弦波或者锯齿波,只要让DA转化的从0到4096也可以;
五、IIC:
过程:首先在主模式下,I2C接口启动数据传输并产生时钟信号,数据和地址都是按八位/字节,高位在前(MSB最高位有效字节)软件控制起始和停止条件。
产生iic起始信号时先有SDA线输出(最下面那行),将数据线和时钟线都输入高电平,过了中间的起始信号的建立时间 Tsu:sta后将数据线从高拉到低发出起始信号,期间需要起始信号保持时间 Thd:sta然后拉低时钟开始数据传输。
0x80=1000 00000x80=1000 0000 若拿如何一个位将这两个进行与运算=1000 0000 只有第一位被保留下来。通过&0x80就会保留最高位的数据,舍弃后七位的数据,
至最后要在第八位之后发送一个效应位ACK(Acknowledge character)
五、RC522&OLED:
SPI协议–RC522滴卡:
OLED:本屏所用的驱动 IC 为 SSD1306;其具 有内部升压功能;所以在设计的时候不需要再专一设计 升压电路;
类似这样的,要在用到那两大排引脚,则需要去使能它所在的端口和引脚,像图中所说的如果要用到此,则需要把它接到PA5和PA7
六–RS485&超声波测距&DHT11:
485: 具有支持多个结点(最多32个)、传输距离远达1219m,接受灵敏度高(200mv),能抑制共模干扰(差分传输) 而RS485采用差分信号后,电平范围为-6V至+6V,相对不易损坏接口电路芯片 。
➽RS232传输速率比较低,传输速率为20Kbps,而RS485最高传输速率达10Mbps。过高的传输速率会降低传输距离,在实际应用中,RS485传输速率往往设置为9600bps或更低。
➽工作过程:
在RS485通信网络中,通常使用485收发器将TTL电平转换成RS485的差分信号。MCU的串口控制器TxD发送数据,经485收发器转换成差分信号,传输到总线上。接收数据时,485收发器将总线上的差分信号转化成TTL信号由RxD到串口控制器。
超声波:
➽1、http://www.51hei.com/bbs/dpj-188881-1.html---现象如下,同时注意一定要用5v供电(正常显示如图右),如果是用3.3v供电误差太大简直就只有0.几cm
➽2、知道为什么在宏定义里面换了引脚号,就可能显示不了吗,因为特定引脚可能有特定的定时器或者中断在,也可以有特定引脚有重映射的功能(AFIO)
➽3、有时候移植别人工程的时候一直现象没出来,可以多用那个keilbat来重新理一下
DHT11:
➽
调试经历(在freertos上面):
今天调试DHT11经验,有了波形就一定要看懂对应上去,不然不知道具体是哪一块的延时出了问题,自己要清楚开始信号是不是真的顺利开始了,然后主机发出的请求应答有没有交出数据线的控制权,
还是说因为请求应答的电平太长然后阻碍了从机发应答信号,过了时间后,当然就不应答了,
就是线只有一条,要不输出要不输入,自己要理清楚输出要多久,然后对应电平delay多久,要是电平一直不能底下来,那可能就是程序里面的delay_us出错了,误以为很短的高电平,实际是自己让它这么长的电平。
刚开始测不出来的线条区别是,前者是标准的,后者错误:
后面是时序 把主机开始信号和从机应答的条件信号都给自己拉高和拉低一定时间后,都对上了,结果检验和不通过不知道为啥:
后面知道了原来还是延时的问题,要自己配对延时,就算时序对了,但是读进来的时候,也是因为依据DHT11的数据对时间的要求,读取2个连续的0bit时有可能出错,
于是修改了延时时间发现30us 到60us都可以正常显示.所以自己原来的delay_us(1)就是时间不准的,所以要再弄出来一个读更小的,原来是自己读太慢了,所以读进来的数据出错: