找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2434|回复: 1
收起左侧

stm32F407串口配置寄存器版本

[复制链接]
ID:564326 发表于 2020-3-25 21:57 | 显示全部楼层 |阅读模式
#include  "uart.h"

**********************************************************************
函数功能:uart初始化函数
函数形参:baud 波特率void Uart1_Init(u32 baud)//9600
{
        double USARTDIV = 0.0;
        u32 DIV_MAN = 0;//保存整数
        u32 DIV_FRA = 0;//保存小数
       
        //1. 配置GPIO口  PA9 和 PA10
        RCC->AHB1ENR |= (0x1 << 0);//(1)打开GPIOA的时钟
        GPIOA->MODER &= ~(0xf << 18);
        GPIOA->MODER |= (0xa << 18);//(2)配置PA9和PA10的端口模式(复用功能)
        GPIOA->AFR[1] &= ~(0xff << 4);
        GPIOA->AFR[1] |= (0x77 << 4);//(3)将PA9和PA10复用给UART1

        //2. 配置uart1  (四要素)
        RCC->APB2ENR |= (0x1 << 4);//(1)打开USART1的时钟
       
        //(2)配置CR1寄存器(数据位、校验位)
        USART1->CR1 = 0;//整体清零  有些配置就是希望它是0
        USART1->CR1 |= (0x1 << 2);//使能接收器
        USART1->CR1 |= (0x1 << 3);//使能发送器
        /*
        16 倍过采样
        1 起始位, 8 数据位, n 停止位
        禁止奇偶校验控制(无)
        */
       
        USART1->CR2 &= ~(0x3 << 12);//(3)配置CR2寄存器(1个停止位)
       
        //(4)配置波特率(求USARTDIV,再把USARTDIV的值写到BRR)
        USARTDIV = 84000000.0 / baud / 16;//546.875
        DIV_MAN = USARTDIV;//得到了整数
        DIV_FRA = (USARTDIV - DIV_MAN) * 16 + 0.5;//0.5四舍五入
        USART1->BRR = DIV_MAN << 4 | DIV_FRA;//将整数和小数写入相应的位
       
        //设置usart1的中断优先级
        NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(7-2, 1, 1));
       
        //是NIVC响应USART1中断
        NVIC_EnableIRQ(USART1_IRQn);
       
        //使能模块中断
        USART1->CR1 |= (0x1 << 5);//使能usart1的接收中断
       
        USART1->CR1 |= (0x1 << 13);//(5)使能USART1
}

//全局变量    系统默认会帮他们进行初始化为0
u8 rev_buf[50];
u8 rev_ok;
u32 rev_time;
u8 rev_start;
u8 rev_i;
//编写usart1的中断服务函数  NVIC根据标志位抢CPU的
//只要usart1接收到数据,SR寄存器的第五位就会置起来
//只要SR寄存器的第五位置起来,NVIC就将CPU拉倒这个中断服务函数里面来
void USART1_IRQHandler(void)//公共入口
{
               
//        u8 ret = 0;
       
        if(USART1->SR & (0x1 << 5))//接收中断标志
        {
                rev_buf[rev_i] = USART1->DR;//读取DR寄存器清接收中断标志
                rev_i++;
               
                rev_start = 1;
                rev_time = 0;
                //printf("%c", ret);
        }

}



/*
**********************************************************************
函数功能:uart1发送字符串函数
函数形参:字符串首地址
函数返回值:None
备注:字符串以'\0'结尾
日期:2020年3月6日
作者
版本:V0.0
**********************************************************************
*/
void Uart1_Send_String(u8 *p)
{
        while(*p != '\0')
        {
                while( !(USART1->SR & (0x1 << 7)) );//等待发送缓冲区为空  标志位为1,核心就在这里等
                USART1->DR = *p;
                p++;
        }
}


/*
**********************************************************************
函数功能:uart1接收字符串函数
函数形参:None
函数返回值:None
备注:字符串以'\0'结尾  超时接收。 如果
日期:2020年3月14日
作者
版本:V0.0
**********************************************************************
*/
void Uart_Revcie_String(void)//LED_ON
{
                if(rev_time > 200 )  //定时器中断10us一次  若rev_time > 100 说明1ms没接收到数据
                {
                        if(rev_buf[rev_i-1] == '#')
                        {
                                rev_buf[rev_i-1] = '\0';
                        }
                        else if(rev_buf[rev_i-1] == '\n')
                        {
                                rev_buf[rev_i-2] = '\0';
                        }
                        else
                        {
                                rev_buf[rev_i] = '\0';     //即没有接收到 # 也没有接收到\r\n  超时接收到字符串
                        }
                        rev_i  = 0;
                        rev_start = 0;
                        rev_time = 0;
                        rev_ok = 1;  //接收完成标志
               
          }
}



#pragma import(__use_no_semihosting_swi) //取消半主机状态

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;

int fputc(int ch, FILE *f) {
        while((USART1->SR &(0X01<<7))==0);//等待发送缓冲区为空
                USART1->DR=ch;
  return (ch);
}
int ferror(FILE *f) {
  /* Your implementation of ferror */
  return EOF;
}


void _ttywrch(int ch) {
  while((USART1->SR &(0X01<<7))==0);
                USART1->DR=ch;
}


void _sys_exit(int return_code) {
label:  goto label;  /* endless loop */
}


回复

使用道具 举报

ID:564326 发表于 2020-3-25 22:02 | 显示全部楼层
这是附件

uart_demo.7z

137.14 KB, 下载次数: 10, 下载积分: 黑币 -5

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表