打印
[STM32F1]

STM32F103串口1与串口2共存问题

[复制链接]
3399|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Garen2|  楼主 | 2017-8-29 15:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
  • /****************************************************************************
  • * Copyright (C), 2014 奋斗嵌入式工作室 www.ourstm.net
  • *
  • * 本例程在 奋斗版STM32开发板TINY上调试通过
  • * QQ: 9191274, 旺旺:sun68, Email: sun68@163.com
  • * 淘宝店铺:ourstm.taobao.com
  • *
  • * 文件名: main.c
  • * 内容简述:
  • *       演示 USART1 当接收到结束符是0x0d 0x0a的数据串时,将接收到的数据传送出去
  •                        V1 LED1闪烁表示正在收发数据。
  • *
  • 定义:
  •         TXD1----- PA9-US1-TX
  •         RXD1----- PA10-US1-RX
  •         速率:115200,n,8,1
  • * 文件历史:
  • * 版本号  日期       作者    说明
  • * v0.1    2014-4-11 sun68  创建该文件
  • *
  • */
  • /* Includes ------------------------------------------------------------------*/
  • #include "stm32f10x.h"
  • #include "stm32f10x_usart.h"
  • #include "misc.h"
  • #include "stdarg.h"
  • /* Private variables ---------------------------------------------------------*/
  • USART_InitTypeDef USART_InitStructure;
  • uint8_t TxBuffer1[] = "USART Interrupt Example: This is USART1 DEMO";
  • uint8_t RxBuffer1[],rec_f,tx_flag;
  • __IO uint8_t TxCounter1 = 0x00;//发送缓冲区
  • __IO uint8_t RxCounter1 = 0x00;//接收缓冲区
  • __IO uint8_t TxCounter2 = 0x00;//发送缓冲区
  • __IO uint8_t RxCounter2 = 0x00;//接收缓冲区
  • uint32_t Rec_Len;
  • /* Private function prototypes -----------------------------------------------*/
  • void RCC_Configuration(void);
  • void GPIO_Configuration(void);
  • void NVIC_Configuration(void);
  • void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...);
  • char *itoa(int value, char *string, int radix);
  • void USART_Config();
  • /****************************************************************************
  • * 名    称:USART_Config(USART_TypeDef* USARTx)
  • * 功    能:配置串口
  • * 入口参数:
  • * 出口参数:无
  • * 说    明:
  • * 调用方法:例如: USART_Config(USART1)
  • ****************************************************************************/
  • void USART_Config(){
  •   USART_InitTypeDef USART_InitStruct;
  •   USART_InitStructure.USART_BaudRate = 9600;                                                //速率115200bps
  •   USART_InitStructure.USART_WordLength = USART_WordLength_8b;                //数据位8位
  •   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_Tx;                                        //收发模式
  •   USART_Init(USART1, &USART_InitStructure);                                                        //配置串口参数函数
  •   USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                    //使能接收中断
  •   USART_ITConfig(USART1, USART_IT_TXE, ENABLE);                                                //使能发送缓冲空中断
  •   USART_Cmd(USART1, ENABLE);
  •    //串2
  •   USART_InitStructure.USART_BaudRate = 9600;                                                //速率115200bps
  •   USART_InitStructure.USART_WordLength = USART_WordLength_8b;                //数据位8位
  •   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_Tx;                                        //收发模式USART_Mode_Rx | USART_Mode_Tx;
  •   USART_Init(USART2, &USART_InitStructure);                                                        //配置串口参数函数
  •   USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);                    //使能接收中断
  •   USART_ITConfig(USART2, USART_IT_TXE, ENABLE);                                                //使能发送缓冲空中断
  •   USART_Cmd(USART2, ENABLE);                                                                                //打开串口二中断
  • }
  • /****************************************************************************
  • * 名    称:int main(void)
  • * 功    能:奋斗板主函数
  • * 入口参数:无
  • * 出口参数:无
  • * 说    明:
  • * 调用方法:无
  • ****************************************************************************/
  • int main(void)
  • {
  •    uint8_t a=0;
  •   /* System Clocks Configuration */
  •   RCC_Configuration();                                                                                          //系统时钟设置
  •   /*嵌套向量中断控制器
  •       配置了USART1的优先级分组为0,抢占优先级级别0(无) ,和响应优先级级别0(0-7) */
  •   NVIC_Configuration();                                                                                          //中断源配置
  •   /*对控制LED指示灯的IO口进行了初始化,将端口配置为推挽上拉输出,口线速度为50Mhz。PA9,PA10端口复用为串口1的TX,RX。
  •   在配置某个口线时,首先应对它所在的端口的时钟进行使能。否则无法配置成功,由于用到了端口B, 因此要对这个端口的时钟
  •   进行使能,同时由于用到复用IO口功能用于配置串口。因此还要使能AFIO(复用功能IO)时钟。*/
  •   GPIO_Configuration();                                                                                          //端口初始化
  •   USART_Config();                                                                                          //串口1初始化
  •   USART_OUT(USART1,"USART1FFF\r\n");
  •   USART_OUT(USART2,"USART2\r\n");
  •   USART_OUT(USART1,"USART1FFF\r\n");
  •    while (1)
  •   {
  •         if(rec_f==1){                                                                                                  //判断是否收到一帧有效数据
  •                 rec_f=0;
  •                 USART_OUT(USART2,"\r\n您发送的信息为: \r\n");
  •                 USART_OUT(USART2,&TxBuffer1[0]);
  •                 if(a==0) {GPIO_SetBits(GPIOB, GPIO_Pin_5); a=1;}          //LED1  V6(V3V5板) V2(MINI板) 明暗闪烁
  •                 else {GPIO_ResetBits(GPIOB, GPIO_Pin_5);a=0;  }
  •         }
  •   }
  • }
  • /****************************************************************************
  • * 名    称:void RCC_Configuration(void)
  • * 功    能:系统时钟配置为72MHZ, 外设时钟配置
  • * 入口参数:无
  • * 出口参数:无
  • * 说    明:
  • * 调用方法:无
  • ****************************************************************************/
  • void RCC_Configuration(void)
  • {
  •    SystemInit();
  •    RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO , ENABLE);
  •    RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 , ENABLE);
  •    //串2
  •    RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE);
  • }
  • /****************************************************************************
  • * 名    称:void GPIO_Configuration(void)
  • * 功    能:通用IO口配置
  • * 入口参数:无
  • * 出口参数:无
  • * 说    明:
  • * 调用方法:
  • ****************************************************************************/
  • void GPIO_Configuration(void)
  • {
  •   GPIO_InitTypeDef GPIO_InitStructure;
  •   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;                                     //LED1控制--PB5
  •   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                         //推挽输出
  •   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  •   GPIO_Init(GPIOB, &GPIO_InitStructure);
  •   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;                                  //USART1 TX
  •   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                     //复用推挽输出
  •   GPIO_Init(GPIOA, &GPIO_InitStructure);                                     //A端口
  •   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;                          //USART1 RX
  •   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;            //复用浮空输入
  •   GPIO_Init(GPIOA, &GPIO_InitStructure);                                  //A端口
  •    //串2
  •   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;                                  //USART2 TX
  •   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                     //复用推挽输出
  •   GPIO_Init(GPIOA, &GPIO_InitStructure);                                     //A端口
  •   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;                                   //USART2 RX
  •   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;            //复用开漏输入
  •   GPIO_Init(GPIOA, &GPIO_InitStructure);                                  //A端口
  • }
  • /****************************************************************************
  • * 名    称:void NVIC_Configuration(void)
  • * 功    能:中断源配置
  • * 入口参数:无
  • * 出口参数:无
  • * 说    明:
  • * 调用方法:无
  • ****************************************************************************/
  • void NVIC_Configuration(void)
  • {
  •   /*  结构声明*/
  •   NVIC_InitTypeDef NVIC_InitStructure;
  •   /* Configure the NVIC Preemption Priority Bits */
  •   /* Configure one bit for preemption priority */
  •   /* 优先级组 说明了抢占优先级所用的位数,和响应优先级所用的位数   在这里是0, 4
  •   0组:  抢占优先级占0位, 响应优先级占4位
  •   1组:  抢占优先级占1位, 响应优先级占3位
  •   2组:  抢占优先级占2位, 响应优先级占2位
  •   3组:  抢占优先级占3位, 响应优先级占1位
  •   4组:  抢占优先级占4位, 响应优先级占0位
  •   */
  •   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  •   NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;                                     //设置串口1中断
  •   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;                     //抢占优先级 0
  •   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;                                //子优先级为0
  •   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                        //使能
  •   NVIC_Init(&NVIC_InitStructure);
  •    //串2
  •   NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;                                     //设置串口2中断
  •   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;                     //抢占优先级 0
  •   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;                                //子优先级为0
  •   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                        //使能
  •   NVIC_Init(&NVIC_InitStructure);
  • }
  • /****************************************************************************
  • * 名    称:void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...)
  • * 功    能:格式化串口输出函数
  • * 入口参数:USARTx:  指定串口
  •                         Data:   发送数组
  •                         ...:     不定参数
  • * 出口参数:无
  • * 说    明:格式化串口输出函数
  •                 "\r"        回车符           USART_OUT(USART1, "abcdefg\r")
  •                         "\n"        换行符           USART_OUT(USART1, "abcdefg\r\n")
  •                         "%s"        字符串           USART_OUT(USART1, "字符串是:%s","abcdefg")
  •                         "%d"        十进制           USART_OUT(USART1, "a=%d",10)
  • * 调用方法:无
  • ****************************************************************************/
  • void USART_OUT(USART_TypeDef* USARTx, uint8_t *Data,...){
  •         const char *s;
  •     int d;
  •     char buf[16];
  •     va_list ap;
  •     va_start(ap, Data);
  •         while(*Data!=0){                                                          //判断是否到达字符串结束符
  •                 if(*Data==0x5c){                                                                          //'\'
  •                         switch (*++Data){
  •                                 case 'r':                                                                  //回车符
  •                                         USART_SendData(USARTx, 0x0d);
  •                                         Data++;
  •                                         break;
  •                                 case 'n':                                                                  //换行符
  •                                         USART_SendData(USARTx, 0x0a);
  •                                         Data++;
  •                                         break;
  •                                 default:
  •                                         Data++;
  •                                     break;
  •                         }
  •                 }
  •                 else if(*Data=='%'){                                                                          //
  •                         switch (*++Data){
  •                                 case 's':                                                                                  //字符串
  •                         s = va_arg(ap, const char *);
  •                         for ( ; *s; s++) {
  •                             USART_SendData(USARTx,*s);
  •                                                 while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);
  •                         }
  •                                         Data++;
  •                         break;
  •                     case 'd':                                                                                  //十进制
  •                         d = va_arg(ap, int);
  •                         itoa(d, buf, 10);
  •                         for (s = buf; *s; s++) {
  •                             USART_SendData(USARTx,*s);
  •                                                 while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);
  •                         }
  •                                         Data++;
  •                         break;
  •                                 default:
  •                                         Data++;
  •                                     break;
  •                         }
  •                 }
  •                 else USART_SendData(USARTx, *Data++);
  •                 while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);
  •         }
  • }
  • /******************************************************
  •                 整形数据转字符串函数
  •         char *itoa(int value, char *string, int radix)
  •                 radix=10 标示是10进制        非十进制,转换结果为0;
  •             例:d=-379;
  •                 执行        itoa(d, buf, 10); 后
  •                 buf="-379"
  • **********************************************************/
  • char *itoa(int value, char *string, int radix)
  • {
  •     int     i, d;
  •     int     flag = 0;
  •     char    *ptr = string;
  •     /* This implementation only works for decimal numbers. */
  •     if (radix != 10)
  •     {
  •         *ptr = 0;
  •         return string;
  •     }
  •     if (!value)
  •     {
  •         *ptr++ = 0x30;
  •         *ptr = 0;
  •         return string;
  •     }
  •     /* if this is a negative value insert the minus sign. */
  •     if (value < 0)
  •     {
  •         *ptr++ = '-';
  •         /* Make the value positive. */
  •         value *= -1;
  •     }
  •     for (i = 10000; i > 0; i /= 10)
  •     {
  •         d = value / i;
  •         if (d || flag)
  •         {
  •             *ptr++ = (char)(d + 0x30);
  •             value -= (d * i);
  •             flag = 1;
  •         }
  •     }
  •     /* Null terminate the string. */
  •     *ptr = 0;
  •     return string;
  • } /* NCL_Itoa */
  • /******************* (C) COPYRIGHT 2013 奋斗STM32 *****END OF FILE****/

说明:
/****************************************************************************
* 名    称:void RCC_Configuration(void)
* 功    能:系统时钟配置为72MHZ, 外设时钟配置
* 入口参数:无
* 出口参数:无
* 说    明:
* 调用方法:无
****************************************************************************/
void RCC_Configuration(void)
{
   SystemInit();
   RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO , ENABLE);
   RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1 , ENABLE);//注解这句串口2正常

   //串2
   RCC_APB1PeriphClockCmd( RCC_APB1Periph_USART2, ENABLE); //注解这句串口1正常
}
单独打开一个串口可以正常工作,如果两个同时打开,则两个都不能正常使用.求助.
沙发
Ryze| | 2017-8-29 15:58 | 只看该作者
是不是 GROUP0 抢占优先级不能设为1

使用特权

评论回复
板凳
Varus| | 2017-8-29 16:06 | 只看该作者
问题应该不在这里

使用特权

评论回复
地板
Snow7| | 2017-8-29 16:19 | 只看该作者
串口1和串口2 是可以正常用的,这个没问题的。

使用特权

评论回复
5
mmuuss586| | 2017-8-29 16:20 | 只看该作者
单独打开,2个都可以;
2个都打开,都不能工作;

具体你怎么测试的?
先写个循环程序,看2个串口都能不能发出数据;

使用特权

评论回复
6
android2| | 2017-8-29 16:40 | 只看该作者

本来几个串口就是可以共存的,这个无需多疑,要么就是没有配置好

使用特权

评论回复
7
拉克丝| | 2017-8-29 16:52 | 只看该作者
是不是这句话搞得鬼?

GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);

使用特权

评论回复
8
309030| | 2017-8-29 17:06 | 只看该作者

RxBuffer1[RxCounter1++] = USART_ReceiveData(USART1);   //将读寄存器的数据缓存到接收缓冲区里
        
    if(RxBuffer1[RxCounter1-2]==0x0d&&RxBuffer1[RxCounter1-1]==0x0a)     //判断结束标志是否是0x0d 0x0a
    {
          for(i=0; i< RxCounter1; i++) TxBuffer1[i]        = RxBuffer1[i];              //将接收缓冲器的数据转到发送缓冲区,准备转发
          rec_f=1;                                                                                                                         //接收成功标志
          TxBuffer1[RxCounter1]=0;                                                     //发送缓冲区结束符   
          RxCounter1=0;
         
    }

这里面写错了,串口2的中断处理程序处,RxCounter1=0;改成RxCounter2=0;

使用特权

评论回复
9
lefeng| | 2017-8-29 17:21 | 只看该作者
请问怎么解决?

使用特权

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

本版积分规则

153

主题

734

帖子

3

粉丝