打印

STM32F4 USART(RS485)发送与接收----(寄存器操作)

[复制链接]
9268|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
固桐|  楼主 | 2013-6-1 21:29 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
串口是我们调试硬件经常用到的一个外设,本设计所采用的接口芯片为SP3485,芯片的使用方法就不多说了,大家可以自己看芯片手册.
下面贴出usart的驱动程序
/*
* Author                :固桐
* History
* --------------------
* Rev                        : 0.00
* Date                        : 01/06/2013
*
* create.
* --------------------
*/
//-----------------Include files-------------------------//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdarg.h>
#include "stm32f4xx.h"
#include "..\include\usart.h"
#include "..\include\hardware.h"
//-----------------Variable------------------------------//

static int send_string_to_usart2(char * str);
static int send_byte_to_usart2(char data);
static int initialize_usart2(int baudrate);
static int my_printf_uart2(const char * fmt, ...);

//-----------------function------------------------------//

static int initialize_usart2(int baudrate)
{
        float temp;
u16 mantissa;
        u16 fraction;

RCC->AHB1ENR |= 0x00000001; //open  A clock
RCC->APB1ENR &= 0xFFFDFFFF;
RCC->APB1ENR |= 0x00020000;//open  usart2 clock
       

        GPIOA->MODER &= 0xFFFFFF0F; //
GPIOA->MODER |= 0x000000A0;      
     
GPIOA->OSPEEDR &= 0xFFFFFFCF; //
GPIOA->OSPEEDR |= 0x00000020;  
   
  GPIOA->PUPDR &= 0xFFFFFFCF; //
  GPIOA->PUPDR |= 0x00000010;

    GPIOA->MODER &= 0xFFFFFFF3; //Configure RS485 DIR(PA.1)
    GPIOA->MODER |= 0x00000004;
    GPIOA->OTYPER &= 0x0000FFFD;
    GPIOA->PUPDR &= 0xFFFFFFF3;
    GPIOA->PUPDR |= 0x00000004;
       
        GPIOA->OSPEEDR &= 0xFFFFFFF3;
        GPIOA->OSPEEDR |= 0x00000008;  
       
    GPIOA->AFR[0] |= 0x00007700; //Configure  (PA.2)(PA.3)
       
        temp = 42000000/ (16 * baudrate);      //串口使用APB1= 1/4CPU CLK=42M;
          
        temp=(float)(42*1000000)/(baudrate*16);//得到USARTDIV
        mantissa=floor(temp);                                 //得到整数部分
        fraction=(temp-mantissa)*16; //得到小数部分  
mantissa<<=4;
        mantissa+=fraction;
        USART2->BRR = mantissa;


//-----------------相应的寄存器操作,参考RM0090数据手册------------------------------//
        USART2->CR1 &=~((1<<12) | (1<<10) );//0
USART2->CR1 |= ((1<<3) | (1<<2) | (1<<8) | (1<<5)| (1<<13));//1
       
        USART2->CR2 &=~((1<<13)| (1<<12) | (1<<11)| (1<<10)| (1<<8) );
        USART2->CR2 |=(1<<9) ;

USART2->CR3 &=~((1<<8)| (1<<9));
       
        RS485_R;   //485芯片处于接收状态

        return 0;
}

//-----------------发送字符------------------------------//
static int
send_byte_to_usart2(char data)
{
        RS485_T;

        USART2->DR= data;

        while (!(USART2->SR & 0x00000040 )) ;

        RS485_R;

        return 0;
}

//-----------------发送字符串------------------------------//
static int
send_string_to_usart2(char * str)
{
        RS485_T;

        while (*str != '\0') {
                while (!((USART2->SR) & 0x00000040 )) ;
                USART2->DR = (*str++);
        }
        while (!(USART2->SR & 0x00000040 )) ;
        RS485_R;

        return 0;
}

//-----------------中断接收------------------------------//
int
USART2_IRQHandler(void)
{
       
        while (!(USART2->SR & 0x00000020 )) ;
                        usart2.receive_buffer[usart2.receive_count++] = USART2->DR;
        if (usart2.receive_buffer[usart2.receive_count - 1] == '\n') {
                usart2.receive_buffer[usart2.receive_count - 1] = 0;
                usart2.receive_count = 0;
                usart2.receive_ok_flag = 1;
        }

        return 0;
}


static int
my_printf_uart2(const char * fmt, ...)
{
        va_list arg_ptr;
        char buf[BUFFER_SIZE];

        memset(buf, '\0', sizeof(buf));

        va_start(arg_ptr, fmt);
        vsprintf(buf, fmt, arg_ptr);
        va_end(arg_ptr);

        send_string_to_usart2(buf);

        return 0;
}
沙发
MOn51| | 2013-6-2 08:31 | 只看该作者
不错!库操作也好!

使用特权

评论回复
板凳
hawksabre| | 2013-6-2 21:25 | 只看该作者
很好的库函数   谢谢楼主的整理   谢谢了

使用特权

评论回复
地板
diyocean| | 2013-6-14 10:57 | 只看该作者
不错  很经典的串口代码

使用特权

评论回复
5
lhchen922| | 2013-10-23 09:01 | 只看该作者
不错

使用特权

评论回复
6
airwill| | 2013-10-23 09:18 | 只看该作者
这样的代码是比较精练的, 但有问题
73.        USART2->CR1 &=~((1<<12) | (1<<10) );//0
这样的可读性不好.
        USART2->CR1 =  USART_CR1_RE | USART_CR1_TE | USART_CR1_RXNEIE |
                        USART_CR1_PCE | USART_CR1_M | USART_CR1_RTOIE;
看看我这样的写法, 是不是好一点.
usart 是直接支持 485 接口的, 可以尽量使用硬件功能, 而不需要这样的指令.
105.        RS485_T;
112.        RS485_R;

使用特权

评论回复
7
Jason_Ding| | 2013-10-24 09:26 | 只看该作者
airwill 发表于 2013-10-23 09:18
这样的代码是比较精练的, 但有问题
73.        USART2->CR1 &=~((1

恩,版主这样写法的可读性、可移植性都增强了很多,赞!

使用特权

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

本版积分规则

7

主题

15

帖子

1

粉丝