打印
[其他ST产品]

STM32F1常用外设介绍

[复制链接]
楼主: 范德萨发额
手机看帖
扫描二维码
随时随地手机跟帖
261
范德萨发额|  楼主 | 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);

使用特权

评论回复
262
范德萨发额|  楼主 | 2023-2-28 21:16 | 只看该作者
在中断函数外获取标志位函数

FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);

使用特权

评论回复
263
范德萨发额|  楼主 | 2023-2-28 21:16 | 只看该作者
在中断函数外清除标志位函数

void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);

使用特权

评论回复
264
范德萨发额|  楼主 | 2023-2-28 21:24 | 只看该作者
在中断函数内获取标志位函数

ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);

使用特权

评论回复
265
范德萨发额|  楼主 | 2023-2-28 21:24 | 只看该作者
在中断函数内清除标志位函数

void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

使用特权

评论回复
266
范德萨发额|  楼主 | 2023-2-28 21:24 | 只看该作者
串口通信程序示例
#include "stm32f10x.h"                  // Device header
#include <stdio.h>
#include <stdarg.h>

void Serial_Init(void)
{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
       
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        USART_InitTypeDef USART_InitStructure;
        USART_InitStructure.USART_BaudRate = 9600;//波特率
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无流控
        USART_InitStructure.USART_Mode = USART_Mode_Tx;//发送模式
        USART_InitStructure.USART_Parity = USART_Parity_No;//无校验位
        USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位一位
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位1字节
        USART_Init(USART1, &USART_InitStructure);
       
        USART_Cmd(USART1, ENABLE);//开启串口
}

void Serial_SendByte(uint8_t Byte)//发送字符
{
        USART_SendData(USART1, Byte);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void Serial_SendArray(uint8_t *Array, uint16_t Length)//发送数组
{
        uint16_t i;
        for (i = 0; i < Length; i ++)
        {
                Serial_SendByte(Array[i]);
        }
}

void Serial_SendString(char *String)//发送字符串
{
        uint8_t i;
        for (i = 0; String[i] != '\0'; i ++)
        {
                Serial_SendByte(String[i]);
        }
}

uint32_t Serial_Pow(uint32_t X, uint32_t Y)
{
        uint32_t Result = 1;
        while (Y --)
        {
                Result *= X;
        }
        return Result;
}

void Serial_SendNumber(uint32_t Number, uint8_t Length)//发送数字
{
        uint8_t i;
        for (i = 0; i < Length; i ++)
        {
                Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 + '0');
        }
}

int fputc(int ch, FILE *f)//重定向printf
{
        Serial_SendByte(ch);
        return ch;
}

void Serial_Printf(char *format, ...)//重定向printf多串口使用
{
        char String[100];
        va_list arg;
        va_start(arg, format);
        vsprintf(String, format, arg);
        va_end(arg);
        Serial_SendString(String);
}

使用特权

评论回复
267
范德萨发额|  楼主 | 2023-2-28 21:24 | 只看该作者
串口收发数据包

数据包的作用是:把一个个单独的数据给打包起来,方便进行多字节的数据通信,例如,陀螺仪传感器,需要用串口发送数据到STM32,陀螺仪的数据,X轴为一个字节、Y轴为一个字节、Z轴一个字节,一共3个数据需要连续不断的发送,当我像这样XYZXYZXYZ连续发送的时候,接受方不知道这个数据哪个对应Y,哪个对应X,哪个对应Z,因为接收方可能从任意的位置接收,所以可能出现数据错位的现象,我们需要一种方式把数据进行分割,把XYZ这一批数据分割开来,分割成一批批数据包,这样在接收的时候,就知道了,数据包第一个数据就是X,数据包第二个数据就是Y,数据包第三个数据就是Z,这就是数据包的任务,就是把同一批的数据进行打包和分割。

使用特权

评论回复
268
范德萨发额|  楼主 | 2023-2-28 21:24 | 只看该作者
串口数据包,通常使用的是额外添加包头包尾的这种方式

防止数据包包头包尾和数据重复的方法,第一种,限制载荷数据的范围,在发送的时候对数据进行限幅,第二种,尽量使用固定长度的数据包,第三种,增加包头包尾的数量,并且让它尽量呈现出载荷数据出现不了的状态。

使用特权

评论回复
269
范德萨发额|  楼主 | 2023-2-28 21:25 | 只看该作者
串口收发Hex数据包

使用特权

评论回复
270
范德萨发额|  楼主 | 2023-2-28 21:26 | 只看该作者
串口收发文本数据包

使用特权

评论回复
271
范德萨发额|  楼主 | 2023-2-28 21:26 | 只看该作者
数据包的收发流程
数据包的发送

数据包的接收

接收固定包长的数据包,设计一种能够记住不同状态的机制,在不同状态执行不同的操作,同时还要进行状态的合理转移,这种程序设计思维叫做“状态机”。

使用特权

评论回复
272
范德萨发额|  楼主 | 2023-2-28 21:26 | 只看该作者

第一个状态是等待包头,第二个状态是接收数据,第三个状态是等待包尾,每个状态需要一个变量来标志一下,类似于置置标志位,标志位只有0和1,状态机是多标志位的一种方式

使用特权

评论回复
273
范德萨发额|  楼主 | 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,回到最初的状态,开始下一个轮回。

使用特权

评论回复
274
范德萨发额|  楼主 | 2023-2-28 21:26 | 只看该作者
状态机使用的基本步骤:先根据项目要求,画几个圈,考虑好各个状态在什么情况下会进行转移,如何转移,画好线和转移条件,最后根据图来进行编程,例如,做个菜单,按什么键,切换什么菜单,执行什么程序。

使用特权

评论回复
275
范德萨发额|  楼主 | 2023-2-28 21:26 | 只看该作者

使用特权

评论回复
276
范德萨发额|  楼主 | 2023-2-28 21:27 | 只看该作者
I2C

    I2C总线(Inter IC Bus)
    两根通信线:SCL(Serial Clock)、SDA(Serial Data)
    同步,半双工
    带数据应答
    支持总线挂在多设备(一主多从、多主多从)
    起始条件:SCL高电平期间,SDA从高电平切换到低电平
    终止条件:SCL高电平期间,SDA从低电平切换到高电平
    每个时序单元的SCL都是以低电平开始,低电平结束
    从机不允许产生起始和终止
————————————————

使用特权

评论回复
277
范德萨发额|  楼主 | 2023-2-28 21:27 | 只看该作者

使用特权

评论回复
278
范德萨发额|  楼主 | 2023-2-28 21:27 | 只看该作者
发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次即可发生一个字节

使用特权

评论回复
279
范德萨发额|  楼主 | 2023-2-28 21:27 | 只看该作者

使用特权

评论回复
280
范德萨发额|  楼主 | 2023-2-28 21:27 | 只看该作者
主机拉低SCL,把数据放在SDA上,主机松开SCL,从机读取SDA的数据

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则