串口通信实验

来源:互联网 发布:算法描述的发展现状 编辑:程序博客网 时间:2024/06/06 18:02

前置技能

  串行通信基本原理
  USART串口通信配置

一,串口操作相关库函数:

获取状态标志位函数-操作USART_SR寄存器

// 获取状态标志位FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG);// 清除状态标志位void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG);// 获取中断状态标志位ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);// 清除中断状态标志位void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

接收发送数据函数-操作USART_DR寄存器

// 发送数据到串口(通过写USART_DR寄存器发送数据)void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);// 接收数据(从USART_DR寄存器读取接收到的数据)uint16_t USART_ReceiveData(USART_TypeDef* USARTx);

串口配置函数

// 串口初始化:波特率,数据字长,奇偶校验,硬件流控以及收发使能void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);// 使能串口void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState);// 使能相关中断void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);

二,串口配置的步骤

1,串口时钟使能,GPIO时钟使能     RCC_APB2PeriphClockCmd()2,串口复位     USART_DeInit();3,GPIO端口模式设置     GPIO_Init();4,串口参数初始化     USART_Init()5,开启中断并初始化NVIC     NVIC_Init();     USART_ITConfig();6,使能串口     USART_Cmd();7,中断函数逻辑     USARTx_IRQHandler();8,串口数据发送     void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);     uint16_t USART_ReceiveData(USART_TypeDef* USARTx);9,串口传输状态获取     ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT);     void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT);

三,串口引脚配置

串口引脚配置

 USART1_TX : 复用推挽输出 USART1_RX : 浮空输入

四,设计串口通信协议

 数据以(0x0D),(0x0A)结尾(回车,换行符)时,认为数据接收完成 如:ABCDEFGHIJK…..(0x0D),(0x0A)

五,代码实现

SYSTEM/usart/usart.h头文件

#ifndef __USART_H#define __USART_H#include "stdio.h"#include "sys.h"#define USART_REC_LEN          200       // 最大接收字节数 200#define EN_USART1_RX           1extern u8  USART_RX_BUF[USART_REC_LEN];  // 串口接收数据缓冲数组-200字节// 16位接收状态标记://      0-13位接收有效数据数量  //      14位:接收到0x0D标志 //      15位:接收完成标志extern u16 USART_RX_STA;//设置串口波特率void uart_init(u32 bound);#endif

SYSTEM/usart/usart.c

u8 USART_RX_BUF[USART_REC_LEN];     // 串口接收数据缓冲数组   200字节// 16位接收状态标记://      0-13位接收有效数据数量 //      14位:接收到0x0D标志 //      15位:接收完成标志u16 USART_RX_STA=0;void uart_init(u32 bound){  GPIO_InitTypeDef GPIO_InitStructure;  USART_InitTypeDef USART_InitStructure;  NVIC_InitTypeDef NVIC_InitStructure;  // 初始化GPIOA,USART1时钟  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);  //USART1_TX    GPIOA.9  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;       // 复用推挽输出  GPIO_Init(GPIOA, &GPIO_InitStructure);  //USART1_RX    GPIOA.10  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空输入  GPIO_Init(GPIOA, &GPIO_InitStructure);  //Usart1 NVIC 中断优先级配置  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;         // 串口1  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;  // 抢占3  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        // 响应1  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           // 使能-开启  NVIC_Init(&NVIC_InitStructure);  //USART配置  USART_InitStructure.USART_BaudRate = bound;                 // 设置波特率-外部传参  USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长 8|9  USART_InitStructure.USART_StopBits = USART_StopBits_1;      // 停止位-1位  USART_InitStructure.USART_Parity = USART_Parity_No;         // 奇偶校验  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;// 硬件流控制  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 使能接收发送  USART_Init(USART1, &USART_InitStructure);       // 初始化串口1  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);  // 开启串口接收中断  USART_Cmd(USART1, ENABLE);                      // 使能串口1}void USART1_IRQHandler(void){    u8 Res;    //判断是否是接收中断    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){        // 读取接收到的数据        Res =USART_ReceiveData(USART1);            // 读取USART_RX_STA-bit15判断是否上一次已经接收完成了,还没有清标志位(外部主函数还没读走)        if((USART_RX_STA&0x8000)==0){            // 读取USART_RX_STA-bit14            if(USART_RX_STA&0x4000){ // 已接收到0x0D                //本次不是0x0A-错误数据,置位USART_RX_STA重新读取                if(Res!=0x0a)USART_RX_STA=0;                else USART_RX_STA|=0x8000;    //本次是0x0A,置位USART_RX_STA-Bit15=1            } else { // 如果上一次没有接收到0x0D                //本次是0x0D,置位USART_RX_STA-Bit14=1                if(Res==0x0d){                    USART_RX_STA|=0x4000;                }else{//本次不是0x0D,存入字节数组,更新数量                    USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;                    USART_RX_STA++;                    //判断超长-如果超长,置位USART_RX_STA重新接收                    if(USART_RX_STA>(USART_REC_LEN-1))                    {                        USART_RX_STA=0;                    }                }            }         }     }}

USER/main.c 主函数

#include "led.h"#include "delay.h"#include "key.h"#include "sys.h"#include "usart.h" int main(void) {    u16 t;                      // 循环计数器    u16 len;                    // 接收到的数据长度    u16 times=0;                // 每10ms+1    delay_init();               // 延迟函数初始化    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组2,2位抢占2位响应    uart_init(115200);          // 设置串口1波特率为115200    LED_Init();                 // LED端口初始化    KEY_Init();                 // 按键端口初始化    // 主循环读取串口数据    while(1)    {        if(USART_RX_STA&0x8000)         // 接收数据完成        {            len=USART_RX_STA&0x3fff;    // 读取数据长短            printf("\r\n您发送的消息为:\r\n\r\n");            for(t=0;t<len;t++)          // 循环发送数据            {                USART_SendData(USART1, USART_RX_BUF[t]);              // 向串口1发送数据                while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);// 等待发送完成            }            printf("\r\n\r\n");         // 换行            USART_RX_STA=0;             // 置位USART_RX_STA,串口下一次接收使用        }else // 接收数据未完成或无数据时        {            times++;            if(times%5000==0)                      // 每50秒            {                printf("\r\n串口实验\r\n");            }            if(times%200==0)printf("2m无数据\n");   // 每2秒            if(times%30==0)LED0=!LED0;             // 每300msLED亮灭切换            delay_ms(10);   // 延时10ms        }    } }

以上代码实现:    电脑通过串口助手发送数据给单片机    单片机接收数据进入接收数据串口中断    根据通信协议处理数据,保存数据到字节数组    将接收到的数据回写给串口,并打印输出
0 0
原创粉丝点击