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

[复制链接]
9867|6
 楼主| 固桐 发表于 2013-6-1 21:29 | 显示全部楼层 |阅读模式
串口是我们调试硬件经常用到的一个外设,本设计所采用的接口芯片为SP3485,芯片的使用方法就不多说了,大家可以自己看芯片手册.
下面贴出usart的驱动程序
  1. /*
  2. * Author                :固桐
  3. * History
  4. * --------------------
  5. * Rev                        : 0.00
  6. * Date                        : 01/06/2013
  7. *
  8. * create.
  9. * --------------------
  10. */
  11. //-----------------Include files-------------------------//

  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <math.h>
  17. #include <stdarg.h>
  18. #include "stm32f4xx.h"
  19. #include "..\include\usart.h"
  20. #include "..\include\hardware.h"
  21. //-----------------Variable------------------------------//

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

  26. //-----------------function------------------------------//

  27. static int initialize_usart2(int baudrate)
  28. {
  29.         float temp;
  30. u16 mantissa;
  31.         u16 fraction;

  32. RCC->AHB1ENR |= 0x00000001; //open  A clock
  33. RCC->APB1ENR &= 0xFFFDFFFF;
  34. RCC->APB1ENR |= 0x00020000;//open  usart2 clock
  35.        

  36.         GPIOA->MODER &= 0xFFFFFF0F; //
  37. GPIOA->MODER |= 0x000000A0;      
  38.      
  39. GPIOA->OSPEEDR &= 0xFFFFFFCF; //
  40. GPIOA->OSPEEDR |= 0x00000020;  
  41.    
  42.   GPIOA->PUPDR &= 0xFFFFFFCF; //
  43.   GPIOA->PUPDR |= 0x00000010;

  44.     GPIOA->MODER &= 0xFFFFFFF3; //Configure RS485 DIR(PA.1)
  45.     GPIOA->MODER |= 0x00000004;
  46.     GPIOA->OTYPER &= 0x0000FFFD;
  47.     GPIOA->PUPDR &= 0xFFFFFFF3;
  48.     GPIOA->PUPDR |= 0x00000004;
  49.        
  50.         GPIOA->OSPEEDR &= 0xFFFFFFF3;
  51.         GPIOA->OSPEEDR |= 0x00000008;  
  52.        
  53.     GPIOA->AFR[0] |= 0x00007700; //Configure  (PA.2)(PA.3)
  54.        
  55.         temp = 42000000/ (16 * baudrate);      //串口使用APB1= 1/4CPU CLK=42M;
  56.           
  57.         temp=(float)(42*1000000)/(baudrate*16);//得到USARTDIV
  58.         mantissa=floor(temp);                                 //得到整数部分
  59.         fraction=(temp-mantissa)*16; //得到小数部分  
  60. mantissa<<=4;
  61.         mantissa+=fraction;
  62.         USART2->BRR = mantissa;


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

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

  72.         return 0;
  73. }

  74. //-----------------发送字符------------------------------//
  75. static int
  76. send_byte_to_usart2(char data)
  77. {
  78.         RS485_T;

  79.         USART2->DR= data;

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

  81.         RS485_R;

  82.         return 0;
  83. }

  84. //-----------------发送字符串------------------------------//
  85. static int
  86. send_string_to_usart2(char * str)
  87. {
  88.         RS485_T;

  89.         while (*str != '\0') {
  90.                 while (!((USART2->SR) & 0x00000040 )) ;
  91.                 USART2->DR = (*str++);
  92.         }
  93.         while (!(USART2->SR & 0x00000040 )) ;
  94.         RS485_R;

  95.         return 0;
  96. }

  97. //-----------------中断接收------------------------------//
  98. int
  99. USART2_IRQHandler(void)
  100. {
  101.        
  102.         while (!(USART2->SR & 0x00000020 )) ;
  103.                         usart2.receive_buffer[usart2.receive_count++] = USART2->DR;
  104.         if (usart2.receive_buffer[usart2.receive_count - 1] == '\n') {
  105.                 usart2.receive_buffer[usart2.receive_count - 1] = 0;
  106.                 usart2.receive_count = 0;
  107.                 usart2.receive_ok_flag = 1;
  108.         }

  109.         return 0;
  110. }


  111. static int
  112. my_printf_uart2(const char * fmt, ...)
  113. {
  114.         va_list arg_ptr;
  115.         char buf[BUFFER_SIZE];

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

  117.         va_start(arg_ptr, fmt);
  118.         vsprintf(buf, fmt, arg_ptr);
  119.         va_end(arg_ptr);

  120.         send_string_to_usart2(buf);

  121.         return 0;
  122. }
MOn51 发表于 2013-6-2 08:31 | 显示全部楼层
不错!库操作也好!
hawksabre 发表于 2013-6-2 21:25 | 显示全部楼层
很好的库函数   谢谢楼主的整理   谢谢了
diyocean 发表于 2013-6-14 10:57 | 显示全部楼层
不错  很经典的串口代码
lhchen922 发表于 2013-10-23 09:01 | 显示全部楼层
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;

Jason_Ding 发表于 2013-10-24 09:26 | 显示全部楼层
airwill 发表于 2013-10-23 09:18
这样的代码是比较精练的, 但有问题
73.        USART2->CR1 &=~((1

恩,版主这样写法的可读性、可移植性都增强了很多,赞!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

7

主题

15

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部