做营销网站推广,wordpress 联盟插件,提升学历一般多少钱,百度网站的安全建设方案USART编码部分(文章最后附上源码)
如果看不懂步骤可以根据源码参考此篇文章就能轻而易举学会USART通信啦#xff01;
编码步骤
第一步 开启时钟
把需要用到的USART和GPIO的时钟打开
第二部 GPIO初始化
把TX配置成复用输出#xff0c;RX配置成输入(上拉输入、浮空输入)。…USART编码部分(文章最后附上源码)
如果看不懂步骤可以根据源码参考此篇文章就能轻而易举学会USART通信啦
编码步骤
第一步 开启时钟
把需要用到的USART和GPIO的时钟打开
第二部 GPIO初始化
把TX配置成复用输出RX配置成输入(上拉输入、浮空输入)。
第三步 配置USART初始化
一个结构体配置所有参数
第四步 发送或接收
只需发送功能
就直接开启USART初始化就结束了
关于发送数据的类型 首先写发送一个字节数据的函数 SendByte函数 调用函数USART_SendData 等待发送寄存器空标志位 发送数组SendArray的函数 函数名形参一个字符指针长度函数体内调用SendByte一位一位的发送数组数据 发送字符串 SendString 的函数 形参为一个字符指针 函数体内使用for循环或while一位一位的发送字符串的每个字节直到遇到\0停止 发送数字SendNumber的函数 形参一个数字类型给32位然后还有一个长度 在函数里面需要把Number的十位个位百位等以十进制拆分开然后转换成字符数字对应的数据一次发送出去 比如12345 取万位就是12345/10000%10得到万位 需要先写一个次方函数 形参是一个X一个y返回值是X的Y次方都是32位 回到SendNumber也是每次发送数据的每一位这个逻辑
需要接收功能 首先配置PA10为上拉输入或者浮空输入 接着在串口初始化里配置接收模式 可以使用查询和中断两种方法 如果使用查询那初始化就结束了 查询的流程是 在主函数里不断判断RXNE标志位如果置1了(if成立)就说明收到数据了 再调用ReceiveData读取DR寄存器就ok了 最后还有清除标志位的问题根据参考手册的寄存器描述进行相应的判断是否需要清除标志位 如果使用中断还需要在USART_cmd之前开去中断配置NVIC那就在开启USART之前再加上ITConfig和NVIC的代码就行了 接着写中断函数在启动文件查找函数名 中断函数里判断接收寄存器非空标志位
接收数据步骤(中断函数建立之后) 定义一个接收数据的变量和一个接受变量的标志位 建立一个接收数据标志位自动请0的函数函数里清零标志位返回1 建立一个返回数据的函数 GetRxData 的函数把接收到了数据返回 上面两部也可以通过把两个变量声明为外部可调用的全局变量 中断函数里引用接收数据函数赋给接收数据的变量置标志位为1证明接收到了数据 主函数里判断标志位如果标志位为1证明接收到了数据 可以在判断函数里使用OLED显示串口接收到的数据然后把这个数据使用串口发送函数再发送到电脑串口助手进行显示
初始化之后 初始化之后如果要发送数据调用一个发送函数就行了 如果要接收数据就调用接收的函数 如果要获取发送和接收的状态就调用获取标志位的函数
USART 函数介绍 USART_ClockInit 和 USART_ClockStrustInit 用来配置同步时钟输出的包括时钟是不是要输出时钟的极性相位等参数 USART_DMACmd 可以开启USART到DMA的触发通道 USART_SendData 发送数据 USART_ReceiveData 接收数据 *发送和接收的时候用*关于子函数
传递字符串
由于字符串自带一个结束标志为所以就不需要传递长度参数 for(i0; String[i] ! ‘\0’; i)
换行Serial_SendString(“\r\n”)
传递数字 加一个偏移 首先定义一个取数字模的函数Serial_Pow Serial_SendByte(Number / Serial_Pow(10, Length - i - 1) % 10 0x30);//0x30可以写成’0’
Printf函数一直方法使用 使用Printf之前打开工程选项勾选Use MicroLIB(是Keil为嵌入式平台优化的一个精简库) 要用的Printf函数就可以用MicroLIB 对Printf进行重定向将Printf打印的东西输出到串口因为printf函数默认输出到屏幕单片机没有屏幕所以要进行重定向。
printf使用步骤 最开始加上#includestdio.h 在最后重写fputc函数。 int fputc(int ch, FILE *F) 这是fputc函数的原型 然后在函数里面把fputc重定向到串口 (Serial_SendByte(ch)); return ch; 这样printf函数就移植好了 最后在串口头文件中包含#includestdio.h相当于main函数内也包含stdio.h
fputc 与 Printf的关系 因为fputc是pritf函数的底层 pritf函数在打印的时候就是不断调用fputc函数一个个打印的 我们把fputc函数重定向到了串口那printf自然就输出到了串口
printf函数在主函数中使用方法
printf(“Num%d\r\n”,666);
如果多个串口都想用Printf的方法
这时就可以用Spritf
Spritf可以把格式化字符输出到一个字符串里 先定义一个字符串(主函数里) char string[100] 然后sprintf第一个参数是打印输出的位置 sprintf(string, “Num%d\r\n”,666); 目前这个格式化的字符在String里 接着Serial_SendString sprintf可以设置打印位置不涉及重定向 所以每个串口都有可以使用Sprintf进行打印
封装Sprintf
由于printf这类函数比较特殊它支持可变的参数 在串口模块里添加头文件 #include stdarg.h 然后在最后对printf函数进行封装 void Serial_Printf(char *format, …) format这个参数用来接收格式化字符串 …三个点用来接收后面的可变参数列表 在函数里面 首先定义输出的字符串 char string[100] va_list arg 定义一个参数列表变量 va_start(arg, format) 从format位置开始接收参数表放在arg里面 之后 vsprintf(string, format, arg) 对于这种封装格式要用vsprintf va_end(arg) 释放参数表 最后是 Serial_SendString(String) 把String发送出去
关于乱码 Serial.c文件程序//也就是串口的.c文件
#include stm32f10x.h // Device header
#include stdio.h
#include stdarg.huint8_t Serial_RxData;
uint8_t Serial_RxFlag;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);GPIO_InitStructure.GPIO_Mode GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin GPIO_Pin_10;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_Mode_Rx;USART_InitStructure.USART_Parity USART_Parity_No;USART_InitStructure.USART_StopBits USART_StopBits_1;USART_InitStructure.USART_WordLength USART_WordLength_8b;USART_Init(USART1, USART_InitStructure);USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority 1;NVIC_Init(NVIC_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)
{Serial_SendByte(ch);return ch;
}void Serial_Printf(char *format, ...)
{char String[100];va_list arg;va_start(arg, format);vsprintf(String, format, arg);va_end(arg);Serial_SendString(String);
}uint8_t Serial_GetRxFlag(void)
{if (Serial_RxFlag 1){Serial_RxFlag 0;return 1;}return 0;
}uint8_t Serial_GetRxData(void)
{return Serial_RxData;
}void USART1_IRQHandler(void)
{if (USART_GetITStatus(USART1, USART_IT_RXNE) SET){Serial_RxData USART_ReceiveData(USART1);Serial_RxFlag 1;USART_ClearITPendingBit(USART1, USART_IT_RXNE);}
}
Serial.h文件程序//也就是串口的.h文件
#ifndef __SERIAL_H
#define __SERIAL_H#include stdio.hvoid Serial_Init(void);
void Serial_SendByte(uint8_t Byte);
void Serial_SendArray(uint8_t *Array, uint16_t Length);
void Serial_SendString(char *String);
void Serial_SendNumber(uint32_t Number, uint8_t Length);
void Serial_Printf(char *format, ...);uint8_t Serial_GetRxFlag(void);
uint8_t Serial_GetRxData(void);#endif
main.c文件程序
#include stm32f10x.h // Device header
#include Delay.h
#include OLED.h
#include Serial.huint8_t RxData;int main(void)
{OLED_Init();OLED_ShowString(1, 1, RxData:);Serial_Init();while (1){if (Serial_GetRxFlag() 1){RxData Serial_GetRxData();Serial_SendByte(RxData);OLED_ShowHexNum(1, 8, RxData, 2);}}
}
感谢各位能坚持看到这里
如果能有机会得到您的一个小赞那我就更有动力了