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

[复制链接]
10716|301
 楼主| 范德萨发额 发表于 2023-2-28 21:08 | 显示全部楼层
智能卡、IrDA函数

void USART_SendBreak(USART_TypeDef* USARTx);
void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime);
void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler);
void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState);
void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState);
void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState);
void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState);
void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState);
void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode);
void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState);
 楼主| 范德萨发额 发表于 2023-2-28 21:16 | 显示全部楼层
在中断函数外获取标志位函数

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);
 楼主| 范德萨发额 发表于 2023-2-28 21:16 | 显示全部楼层
在中断函数外清除标志位函数

void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);
 楼主| 范德萨发额 发表于 2023-2-28 21:24 | 显示全部楼层
在中断函数内获取标志位函数

ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);
 楼主| 范德萨发额 发表于 2023-2-28 21:24 | 显示全部楼层
在中断函数内清除标志位函数

void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);
 楼主| 范德萨发额 发表于 2023-2-28 21:24 | 显示全部楼层
串口通信程序示例
  1. #include "stm32f10x.h"                  // Device header
  2. #include <stdio.h>
  3. #include <stdarg.h>

  4. void Serial_Init(void)
  5. {
  6.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  7.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  8.        
  9.         GPIO_InitTypeDef GPIO_InitStructure;
  10.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  11.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  12.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  13.         GPIO_Init(GPIOA, &GPIO_InitStructure);
  14.        
  15.         USART_InitTypeDef USART_InitStructure;
  16.         USART_InitStructure.USART_BaudRate = 9600;//波特率
  17.         USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无流控
  18.         USART_InitStructure.USART_Mode = USART_Mode_Tx;//发送模式
  19.         USART_InitStructure.USART_Parity = USART_Parity_No;//无校验位
  20.         USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位一位
  21.         USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位1字节
  22.         USART_Init(USART1, &USART_InitStructure);
  23.        
  24.         USART_Cmd(USART1, ENABLE);//开启串口
  25. }

  26. void Serial_SendByte(uint8_t Byte)//发送字符
  27. {
  28.         USART_SendData(USART1, Byte);
  29.         while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
  30. }

  31. void Serial_SendArray(uint8_t *Array, uint16_t Length)//发送数组
  32. {
  33.         uint16_t i;
  34.         for (i = 0; i < Length; i ++)
  35.         {
  36.                 Serial_SendByte(Array[i]);
  37.         }
  38. }

  39. void Serial_SendString(char *String)//发送字符串
  40. {
  41.         uint8_t i;
  42.         for (i = 0; String[i] != '\0'; i ++)
  43.         {
  44.                 Serial_SendByte(String[i]);
  45.         }
  46. }

  47. uint32_t Serial_Pow(uint32_t X, uint32_t Y)
  48. {
  49.         uint32_t Result = 1;
  50.         while (Y --)
  51.         {
  52.                 Result *= X;
  53.         }
  54.         return Result;
  55. }

  56. void Serial_SendNumber(uint32_t Number, uint8_t Length)//发送数字
  57. {
  58.         uint8_t i;
  59.         for (i = 0; i < Length; i ++)
  60.         {
  61.                 Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
  62.         }
  63. }

  64. int fputc(int ch, FILE *f)//重定向printf
  65. {
  66.         Serial_SendByte(ch);
  67.         return ch;
  68. }

  69. void Serial_Printf(char *format, ...)//重定向printf多串口使用
  70. {
  71.         char String[100];
  72.         va_list arg;
  73.         va_start(arg, format);
  74.         vsprintf(String, format, arg);
  75.         va_end(arg);
  76.         Serial_SendString(String);
  77. }

 楼主| 范德萨发额 发表于 2023-2-28 21:24 | 显示全部楼层
串口收发数据包

数据包的作用是:把一个个单独的数据给打包起来,方便进行多字节的数据通信,例如,陀螺仪传感器,需要用串口发送数据到STM32,陀螺仪的数据,X轴为一个字节、Y轴为一个字节、Z轴一个字节,一共3个数据需要连续不断的发送,当我像这样XYZXYZXYZ连续发送的时候,接受方不知道这个数据哪个对应Y,哪个对应X,哪个对应Z,因为接收方可能从任意的位置接收,所以可能出现数据错位的现象,我们需要一种方式把数据进行分割,把XYZ这一批数据分割开来,分割成一批批数据包,这样在接收的时候,就知道了,数据包第一个数据就是X,数据包第二个数据就是Y,数据包第三个数据就是Z,这就是数据包的任务,就是把同一批的数据进行打包和分割。
 楼主| 范德萨发额 发表于 2023-2-28 21:24 | 显示全部楼层
串口数据包,通常使用的是额外添加包头包尾的这种方式

防止数据包包头包尾和数据重复的方法,第一种,限制载荷数据的范围,在发送的时候对数据进行限幅,第二种,尽量使用固定长度的数据包,第三种,增加包头包尾的数量,并且让它尽量呈现出载荷数据出现不了的状态。
 楼主| 范德萨发额 发表于 2023-2-28 21:25 | 显示全部楼层
串口收发Hex数据包
6297763fe00e1e870a.png
 楼主| 范德萨发额 发表于 2023-2-28 21:26 | 显示全部楼层
串口收发文本数据包
9506563fe00f05f250.png
 楼主| 范德萨发额 发表于 2023-2-28 21:26 | 显示全部楼层
数据包的收发流程
数据包的发送

数据包的接收

接收固定包长的数据包,设计一种能够记住不同状态的机制,在不同状态执行不同的操作,同时还要进行状态的合理转移,这种程序设计思维叫做“状态机”。
 楼主| 范德萨发额 发表于 2023-2-28 21:26 | 显示全部楼层
4972363fe00fe0107f.png
第一个状态是等待包头,第二个状态是接收数据,第三个状态是等待包尾,每个状态需要一个变量来标志一下,类似于置置标志位,标志位只有0和1,状态机是多标志位的一种方式
 楼主| 范德萨发额 发表于 2023-2-28 21:26 | 显示全部楼层
执行流程是最开始S = 0,收到一个数据,进中断,根据S = 0,进入第一个状态的程序,判断数据是不是包头FF,如果是FF,则代表收到包头,之后置S = 1,退出中断,结束,这样下次再进中断,根据S = 1,就可以进行接收数据的程序了,在第一个状态,如果收到的不是FF就说明数据包没有对齐,应该等待数据包包头的出现,这时状态仍然是0,下次进中断,就还是判断包头的逻辑,直到出现FF,才能转到下一个状态,之后出现了FF,就可以转移到接收数据的状态了,这时再收到数据,就可以直接把它存在数据中,另外再用一个变量,记录收了多少个数据,如果没收够4个,就一直是接收状态,如果收够了,就置S = 2,下次进中断时,就可以进入下一个状态了,最后一个状态就是等待包尾,判断数据是不是FE,这样就可以置S = 0,回到最初的状态,开始下一个轮回。
 楼主| 范德萨发额 发表于 2023-2-28 21:26 | 显示全部楼层
状态机使用的基本步骤:先根据项目要求,画几个圈,考虑好各个状态在什么情况下会进行转移,如何转移,画好线和转移条件,最后根据图来进行编程,例如,做个菜单,按什么键,切换什么菜单,执行什么程序。
 楼主| 范德萨发额 发表于 2023-2-28 21:26 | 显示全部楼层
 楼主| 范德萨发额 发表于 2023-2-28 21:27 | 显示全部楼层
I2C

    I2C总线(Inter IC Bus)
    两根通信线:SCL(Serial Clock)、SDA(Serial Data)
    同步,半双工
    带数据应答
    支持总线挂在多设备(一主多从、多主多从)
    起始条件:SCL高电平期间,SDA从高电平切换到低电平
    终止条件:SCL高电平期间,SDA从低电平切换到高电平
    每个时序单元的SCL都是以低电平开始,低电平结束
    从机不允许产生起始和终止
————————————————
 楼主| 范德萨发额 发表于 2023-2-28 21:27 | 显示全部楼层
 楼主| 范德萨发额 发表于 2023-2-28 21:27 | 显示全部楼层
发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次即可发生一个字节
 楼主| 范德萨发额 发表于 2023-2-28 21:27 | 显示全部楼层
 楼主| 范德萨发额 发表于 2023-2-28 21:27 | 显示全部楼层
主机拉低SCL,把数据放在SDA上,主机松开SCL,从机读取SDA的数据
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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