单片机
返回首页

STM32之串口通信

2015-11-18 来源:eefocus

实验目的:

实现利用串口1 不停的打印一个信息到电脑上,同时接收从串口发过来的数据,把发送过来的数据直接送回给电脑。

 

实验平台:

基于STM32F103C8T6的彩屏开发板

 

硬件接口:

        [转载]STM32之串口通信

 

注意:因为我的开发板上的串口和LED共用了PA9和PA10,所以在使用USART1时务必屏蔽LED,不然两者会互相影响而导致实现现象无法呈现。

 

相关寄存器:

1,串口时钟使能。串口作为STM32 的一个外设,其时钟由外设时钟使能寄存器控制,这

里我们使用的串口1 是在APB2ENR 寄存器的第14 位。

2,串口复位。串口1 的复位是通过配置APB2RSTR 寄存器的第14 位来实现的。。通过向该位写1来复位串口1,写0 结束复位。

3,串口波特率设置。每个串口都有一个自己独立的波特率寄存器USART_BRR

波特率的计算,STM32 的串口波特率计算公式如下:

                        [转载]STM32之串口通信
上式中, 是给串口的时钟(PCLK1 用于USART2、3、4、5,PCLK2 用于USART1);USARTDIV 是一个无符号定点数。我们只要得到USARTDIV 的值,就可以得到串口波特率寄存器USART1->BRR 的值。

4,串口控制。STM32 的每个串口都有3 个控制寄存器USART_CR1~3,串口的很多配置

都是通过这3 个寄存器来设置的

5,数据发送与接收。STM32 的发送与接收是通过数据寄存器USART_DR 来实现的,这是

一个双寄存器,包含了TDR 和RDR。

6,串口状态。串口的状态可以通过状态寄存器USART_SR 读取。

(注:详细的介绍使用请参考ST公司的数据手册)

 

程序设计:

(注:本人的usart.c usart.h delay.c delay.h sys.c sys.h是引用网上一位网友整理的)

 

    usart.h

#ifndef __USART_H

#define __USART_H

#include

#include 'stdio.h'   

extern u8 USART_RX_BUF[64];     //接收缓冲,最大63个字节.末字节为换行符

extern u8 USART_RX_STA;         //接收状态标记   

 

//如果想串口中断接收,请不要注释以下宏定义

#define EN_USART1_RX //使能串口1接收

void uart_init(u32 pclk2,u32 bound);

 

#endif      

 

 

    usart.c

#include 'sys.h'

#include 'usart.h'

//加入以下代码,支持printf函数,而不需要选择use MicroLIB     

#if 1

#pragma import(__use_no_semihosting)            

//标准库需要的支持函数                

struct __FILE

{

  int handle;

 

 

 

};

 

FILE __stdout;      

//定义_sys_exit()以避免使用半主机模式   

_sys_exit(int x)

{

  x = x;

}

//重定义fputc函数

int fputc(int ch, FILE *f)

    

  while((USART1->SR&0X40)==0);//循环发送,直到发送完毕  

  USART1->DR = (u8) ch;     

  return ch;

}

#endif

//end

//////////////////////////////////////////////////////////////////

 

#ifdef EN_USART1_RX   //如果使能了接收

//串口1中断服务程序

//注意,读取USARTx->SR能避免莫名其妙的错误    

u8 USART_RX_BUF[64];     //接收缓冲,最大64个字节.

//接收状态

//bit7,接收完成标志

//bit6,接收到0x0d

//bit5~0,接收到的有效字节数目

u8 USART_RX_STA=0;       //接收状态标记    

 

void USART1_IRQHandler(void)

{

  u8 res;    

  if(USART1->SR&(1<<5))//接收到数据

  

      res=USART1->DR;

      if((USART_RX_STA&0x80)==0)//接收未完成

      {

          if(USART_RX_STA&0x40)//接收到了0x0d

          {

              if(res!=0x0a)

                  USART_RX_STA=0;//接收错误,重新开始

              else

                  USART_RX_STA|=0x80; //接收完成了

          }else //还没收到0X0D

          

              if(res==0x0d)

                  USART_RX_STA|=0x40;

              else

              {

                  USART_RX_BUF[USART_RX_STA&0X3F]=res;

                  USART_RX_STA++;

                  if(USART_RX_STA>63)USART_RX_STA=0;//接收数据错误,重新开始接收    

                  

          }

                                                    

                                            

}

#endif

//该函数的重点就是判断接收是否完成,通过检测是否收到0X0D、0X0A 的连续2 个字节//(0X0D 后跟0X0A 表示回车键)来检测是否结束。当检测到这个结束序列之后,就会置//位USART_RX_STA 的最高为来标记已经收到了一次数据。之后等待外部函数清空该位//之后才开始第二次接收。所接收的数据全部存放在USART_RX_BUF 里面,一次接收数//据不能超过64个字节,否则被丢弃。                                   

 

 

//初始化IO 串口1

//pclk2:PCLK2时钟频率(Mhz)

//bound:波特率

//CHECK OK

//091209

void uart_init(u32 pclk2,u32 bound)

    

  float temp;

  u16 mantissa;

  u16 fraction;     

  temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV

  mantissa=temp;              //得到整数部分

  fraction=(temp-mantissa)*16; //得到小数部分

    mantissa<<=4;

  mantissa+=fraction;

  RCC->APB2ENR|=1<<2;   //使能PORTA口时钟 

  RCC->APB2ENR|=1<<14;  //使能串口时钟

  GPIOA->CRH&=0XFFFFF00F;

  GPIOA->CRH|=0X000008B0;//IO状态设置

       

  RCC->APB2RSTR|=1<<14;   //复位串口1

  RCC->APB2RSTR&=~(1<<14);//停止复位        

  //波特率设置

  USART1->BRR=mantissa; // 波特率设置

  USART1->CR1|=0X200C;  //1位停止,无校验位.

#ifdef EN_USART1_RX         //如果使能了接收

  //使能接收中断

  USART1->CR1|=1<<8;    //PE中断使能

  USART1->CR1|=1<<5;    //接收缓冲区非空中断使能         

  MY_NVIC_Init(3,3,USART1_IRQChannel,2);//组2,最低优先级

#endif

}

 

  主函数

#include

#include'common.h'   

int main(void)

       

  u8 t;

  u8 len;

  u16 times=0; 

  Stm32_Clock_Init(9); //系统时钟设置

  delay_init(72);      //延时初始化

  uart_init(72,9600); //串口初始化为9600 

  while(1)

  {

      if(USART_RX_STA&0x80)

                         

          len=USART_RX_STA&0x3f;//得到此次接收到的数据长度

          printf('n您发送的消息为:n');

          for(t=0;t

          {

              USART1->DR=USART_RX_BUF[t];

              while((USART1->SR&0X40)==0);//等待发送结束

          }

          printf('nn');//插入换行

          USART_RX_STA=0;

      }else

      {

          times++;

          if(timesP00==0)

          {

              printf('n 简单的串口实验n');

          }

          if(times 0==0)printf('请输入数据,以回车键结束n'); 

          delay_ms(10);  

      }

  

}

 

实验现象:

 

 [转载]STM32之串口通信
 


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 简洁的过零调功器电路设计与分析

  • CCFL的工作原理及电子驱动电路解析

  • MT3608构成3.7V转12V的升压电路图

  • 基于M66T旋律发​​生器的电路图解析

  • 基于CA3193的热电偶放大器电路

  • 基于TDA1554的立体声放大器电路

    相关电子头条文章