打印
[STM32F4]

不知道为什么串口中断进不去?

[复制链接]
4135|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
wenny0000|  楼主 | 2013-12-21 10:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
/*********COM 中断*********/
//


void COM3Init(u32 BaudRate)
{   
          GPIO_InitTypeDef GPIO_InitStructure;
          USART_InitTypeDef USART_InitStructure;                                         

          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
          RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
          GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);  
          GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);
         
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                   // 25M/50/100
          GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
          GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
          GPIO_Init(GPIOB, &GPIO_InitStructure);   
          USART_InitStructure.USART_BaudRate =BaudRate;// BaudRate;   //波特率设置
          USART_InitStructure.USART_WordLength = USART_WordLength_8b;
          USART_InitStructure.USART_StopBits = USART_StopBits_1;
          USART_InitStructure.USART_Parity = USART_Parity_No;
          USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
          USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
          USART_Init(USART3, &USART_InitStructure);
          USART_Cmd(USART3, ENABLE);
          USART_ClearFlag(USART3, USART_FLAG_TC);
}

/**************************************************************************/
void NVIC_Config(void)
{
   NVIC_InitTypeDef NVIC_InitStructure;

   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);                                  //嵌套优先级分组为1
   NVIC_InitStructure.NVIC_IRQChannel=USART3_IRQn;                            //嵌套通道为UART5_IRQn
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;      //抢占优先级为0
   NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;                                //响应优先级为0


   NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;                                   //通道中断使能
   NVIC_Init(&NVIC_InitStructure);

}

/**********************************************************************************/
void USART3_IRQHandler(void)
{
        if(USART_GetITStatus(USART3,USART_IT_RXNE)!=RESET)//判断为接收中断
          { USART_SendData(USART1,USART_ReceiveData(USART3));//发送收到的数据
              /*******
                想做个循环缓冲存储

              *****/
          }
         USART_ClearITPendingBit(USART3, USART_IT_RXNE);   
       
}

/*******************************************************************************/

int main(void)
{

        CQCom1.WrPos = CQCom1.RdPos;
        CQCom3.WrPos = CQCom3.RdPos;
        CQCom5.WrPos = CQCom5.RdPos;

        LED_Init();                                /*LED*************/
        COM1Init(115200*2);                /****COM1 for keyboad***************/
        COM3Init(115200*2);                /****COM2 for debug***************/
        NVIC_Config();

        printf("\n\r Usart1\n\r");                  // COM1 report


/******************************************************************/
while(1)
{

                LEDOn(LED2);
                delay_ms(200);
               
                   delay_ms(200);


   } //end while


} //end main






























沙发
wenny0000|  楼主 | 2013-12-21 10:27 | 只看该作者
串口COM1能够收到板子发出的“Usart1字符。但是COM3进不去中断,这是一个问题,没有搞明白。仔细研学了下相关例程,查看了启动文件,中断向量中有中断服务函数,是否STM系列的中断服务函数挂接就是这样就OK?其二串口的中断函数-接收也好-发送也好,进入中断后,是否就可以直接清除中断标志,有没有一个硬件自动清除的,比如当进入中断收读过接收FIFO并读完就自动清除中断标志呢?”

使用特权

评论回复
板凳
wenny0000|  楼主 | 2013-12-21 10:57 | 只看该作者
困扰了很久,不知道有什么技巧,刚刚入手自己研学中,希望大侠给点指导。。。

使用特权

评论回复
地板
wenny0000|  楼主 | 2013-12-21 11:08 | 只看该作者
突然想到了个奇怪的问题,是否由于时钟问题。
板子采用了个20M的时钟,相关时钟处理如下:
/*******************************************************************/
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET  0x00 /*!< Vector Table base offset field.
                                   This value must be a multiple of 0x200. */
/*---use extr source =20000000 */
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      5
#define PLL_N      84
/* PLL_VCO =336M */
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2
/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
#define PLL_Q      7
/*******************************************************************************/
在主函数中:
COM1Init(115200*2);  
/******************************************************************************/
问题在于:最先使用COMM1Init(115200);初始化后,上位机按115200设置串口,COM1输出“Usart1”字符是不能正确接收的,当如此×2后,上位机在机设置成115200反而能正确接收。
那么是否意味着COM1的串口时钟设置有问题?
但是我在并没有判断接收数据的值,只要有数据有进中断就行。时钟问题最多是接收的数据解析出错而已。郁闷

使用特权

评论回复
5
wenny0000|  楼主 | 2013-12-21 11:14 | 只看该作者
在STM32F4XX_usart.c中关于串口BRR计算如下:
/********************************************************/
/*---------------------------- USART BRR Configuration -----------------------*/
  /* Configure the USART Baud Rate */
  RCC_GetClocksFreq(&RCC_ClocksStatus);

  if ((USARTx == USART1) || (USARTx == USART6))
  {
    apbclock = RCC_ClocksStatus.PCLK2_Frequency;
  }
  else
  {
    apbclock = RCC_ClocksStatus.PCLK1_Frequency;
  }
  
  /* Determine the integer part */
  if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
  {
    /* Integer part computing in case Oversampling mode is 8 Samples */
    integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate)));   
  }
  else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
  {
    /* Integer part computing in case Oversampling mode is 16 Samples */
    integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate)));   
  }
  tmpreg = (integerdivider / 100) << 4;

  /* Determine the fractional part */
  fractionaldivider = integerdivider - (100 * (tmpreg >> 4));

  /* Implement the fractional part in the register */
  if ((USARTx->CR1 & USART_CR1_OVER8) != 0)
  {
    tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);
  }
  else /* if ((USARTx->CR1 & USART_CR1_OVER8) == 0) */
  {
    tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);
  }
  
  /* Write to USART BRR register */
  USARTx->BRR = (uint16_t)tmpreg;
}
/**************************************************************/
其中:   integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate)));    中的25是否有特殊含义呢?没有看的太明白?

使用特权

评论回复
6
gaochy1126| | 2013-12-21 11:50 | 只看该作者
这个不需重映射吧。

使用特权

评论回复
7
gaochy1126| | 2013-12-21 11:50 | 只看该作者
你去掉AF这几条语句试试。

使用特权

评论回复
8
SLHSu37| | 2013-12-21 13:50 | 只看该作者
本帖最后由 SLHSu37 于 2013-12-21 13:53 编辑

RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
这是你复制到帖子里的时候复制错的还是你程序里就是这样写的?
用APB2的命令去开APB1设备的时钟,能好用?

我没搞过F4,不知道F4里串口接收中断在哪里开

接收标志位在中断里清,F1里是这么做的

使用特权

评论回复
评分
参与人数 1威望 +1 收起 理由
wenny0000 + 1 赞一个!
9
wenny0000|  楼主 | 2013-12-21 15:47 | 只看该作者
找到问题了,谢谢大家:
问题结果如下:
         USART_Init(USART3, &USART_InitStructure);
          USART_Cmd(USART3, ENABLE);
          USART_ClearFlag(USART3, USART_FLAG_TC);
在第二句,始能串口前,应该开放接收中断!!!
USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
哈哈
另外:
发送中断只有能在发送函数中进行设置。

使用特权

评论回复
10
wenny0000|  楼主 | 2013-12-21 15:55 | 只看该作者
SLHSu37 发表于 2013-12-21 13:50
RCC_APB2PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
这是你复制到帖子里的时候复制错的还是你程序里 ...

你说的是一个问题,AHB、APB时钟配置问题。感谢中,没有仔细看书,COPY例程没有搞明白,刚才根据你的指引看了看,你讲的是对的,谢谢哦。
虽然不是串口最终不能进去的原因,也很感谢

使用特权

评论回复
11
SLHSu37| | 2013-12-21 17:01 | 只看该作者
wenny0000 发表于 2013-12-21 15:55
你说的是一个问题,AHB、APB时钟配置问题。感谢中,没有仔细看书,COPY例程没有搞明白,刚才根据你的指引 ...

没搞过F4,所以不知道串口中断在哪里开,之前也说过·
你的问题我遇到过,配置时钟出错,没开串口接收中断,仔细一点就好了

使用特权

评论回复
12
ABHK| | 2013-12-21 20:25 | 只看该作者
这个   应该还是时钟的问题   应该还是时钟分频  那里出了问题   

使用特权

评论回复
13
wenny0000|  楼主 | 2013-12-22 09:42 | 只看该作者
关于串口中断的问题已经解决,如9楼所述。

新的问题是在是时钟问题,按 SLHSu37 的指导,修正了串口的时钟配置项:摘抄如下:
void COM3Init(u32 BaudRate)
{   
          GPIO_InitTypeDef GPIO_InitStructure;
          USART_InitTypeDef USART_InitStructure;                                        //what's mean?

          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
          RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
          GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);  
          GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);
         
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                   // 25M/50/100
          GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
          GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
          GPIO_Init(GPIOB, &GPIO_InitStructure);   
         
       
        USART_InitStructure.USART_BaudRate =BaudRate;// BaudRate;//波特率设置
          USART_InitStructure.USART_WordLength = USART_WordLength_8b;
          USART_InitStructure.USART_StopBits = USART_StopBits_1;
          USART_InitStructure.USART_Parity = USART_Parity_No;
          USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
          USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  
          USART_Init(USART3, &USART_InitStructure);
        USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
          USART_Cmd(USART3, ENABLE);
          USART_ClearFlag(USART3, USART_FLAG_TC);
}

结果:main中必须书写成:
        COM1Init(115200*2);                 
        COM3Init(115200/6);       
相关串口才能正确的按照115200波特率与上位机串口进行通讯。
问题:我使用了20M外部时钟,并且
/*---use extr source =20000000 */
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N */
#define PLL_M      5
#define PLL_N      84
/* PLL_VCO =336M */
/* SYSCLK = PLL_VCO / PLL_P */
#define PLL_P      2

/* USB OTG FS, SDIO and RNG Clock =  PLL_VCO / PLLQ */
#define PLL_Q      7
----------------
串口的时钟出现问题在哪里呢?????????????????虽然能用但是没用搞明白,怪怪的。

使用特权

评论回复
14
wenny0000|  楼主 | 2013-12-24 10:06 | 只看该作者
查清楚了一半,COM1Init(115200*2);所有的串口如果要设置成115200,现在就是这样写。看起来是我的哪个地方的时钟搞小了。不纠结了。

使用特权

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

本版积分规则

3

主题

18

帖子

0

粉丝