野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1996|回复: 1

野火标准库教程里21章串口通信作业

[复制链接]
发表于 2023-7-19 10:30:09 | 显示全部楼层 |阅读模式
感觉像是没进入中断,但中断里的收到数据后发送回来有显示,但在中断里加了点灯没有按预期点亮(灯是没有问题的,可以正常点亮)。

21-USART中断接收数据后控制RGB灯.zip (5.79 MB, 下载次数: 15)
野火论坛202307191026352192..png
main.c

#include "stm32f10x.h"
#include "bsp_led.h"
#include "bsp_usart.h"
#include "stm32f10x_it.h"

int main(void)
{               
        USART_Config();  // USART的GPIO初始化
        LED_GPIO_Config();  // LED的GPIO初始化
       
        Usart_SendStr(DEBUG_USARTx, "这是一个通过中断接收数据后控制RGB灯的程序\n");
       
        while (1)
        {               
                switch(ucTemp)
                {
                        case '1':        LED_GREEN;
                                break;
                       
                        case '2':        LED_GREEN;
                                break;
                       
                        case '3':        LED_GREEN;
                                break;
                       
                        default:        LED_RGBOFF;
                                break;
                }
        }
}
bsp.usart.c


#include "bsp_usart.h"

/***** 有中断可能引起实验错误 *****/
static void NVIC_Configuration(void)  // 串口中断优先级配置
{
  NVIC_InitTypeDef NVIC_InitStructure;  // 定义中断结构体
  
  /* 嵌套向量中断控制器组选择 */
        /* 提示 NVIC_PriorityGroupConfig() 在整个工程只需要调用一次来配置优先级分组*/
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* 配置USART为中断源 */
  NVIC_InitStructure.NVIC_IRQChannel = DEBUG_USART_IRQ;
  /* 抢断优先级*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  /* 初始化配置NVIC */
  NVIC_Init(&NVIC_InitStructure);
}

void USART_Config(void)  // 初始化
{
        /* 定义结构体(变量定义一定要在函数的开头) */
        GPIO_InitTypeDef GPIO_InitStructure;  // GPIO结构体
        USART_InitTypeDef USART_InitStructure;  // 串口结构体

        /* 配置GPIO结构体 */
        /* 开时钟 */
        // 打开串口GPIO的时钟
        DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE);  // 串口1 -- GPIOA
       
        // 打开串口外设的时钟
        DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE);

        /* 配置GPIO */
        // 将USART Tx的GPIO配置为推挽复用模式
        // 选引脚
        GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN;  
        // 推挽复用模式
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        // 完成GPIO的初始化配置
        GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure);  

  // 将USART Rx的GPIO配置为浮空输入模式(外部发什么数据就体现什么电平,所以不能上拉也不能下拉,所以配置浮空输入)
        GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure);
       
        /* 配置串口结构体 */
        // 配置串口的工作参数
        // 配置波特率
        USART_InitStructure.USART_BaudRate = DEBUG_USART_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(DEBUG_USARTx, &USART_InitStructure);
       
        // 串口中断优先级配置
        NVIC_Configuration();
       
        // 使能串口接收中断
        USART_ITConfig(DEBUG_USARTx, USART_IT_RXNE, ENABLE);  // 接收数据寄存器非空时产生中断       
       
        // 使能串口
        USART_Cmd(DEBUG_USARTx, ENABLE);        // 把控制寄存器1里的UE位置1(总开关),使能USART
}

/* 发送一个字节数据 */
void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data)
// USART_TypeDef* pUSARTx,p表示指针,指定是哪一个串口;uint8_t data,表示所发送的8位数据
{
        USART_SendData(pUSARTx, data);  // 数据发送
        while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET );        // 检测发送寄存器是否为空(TXE)
}

/* 发送两个字节数据 */
void Usart_SendHalfWord(USART_TypeDef* pUSARTx, uint16_t data)
{
        uint8_t temp_h, temp_l;  // 高八位和低八位数据
       
        temp_h = (data & 0Xff00) >> 8;  //取出高八位
        temp_l = (data & 0Xff);  //取出低八位
       
        USART_SendData(pUSARTx, temp_h);  // 发送高八位
        while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET );

        USART_SendData(pUSARTx, temp_l);  // 发送低八位
        while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET );
}

/* 发送n位数据的数组 */
void Usart_SendArray(USART_TypeDef* pUSARTx, uint8_t *array, uint8_t num)
// 多次调用发送一个字节数据函数
{
        uint8_t i;
        for( i=0; i<num; i++ )
        {
                Usart_SendByte(pUSARTx, array);
        }
        while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET );
}

/* 发送字符串 */
void Usart_SendStr(USART_TypeDef* pUSARTx, uint8_t *str)
// 多次调用发送一个字节数据函数
{
        uint8_t i = 0;
        do
        {
                Usart_SendByte(pUSARTx, *(str+i));
                i++;
        }while(*(str+i) != '\0');  // 字符串以'\0'结束
        while( USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET );
}

/* 重定向c库函数printf到串口,重定向后可使用printf函数 */
int fputc(int ch, FILE *f)
{
                USART_SendData(DEBUG_USARTx, (uint8_t) ch);  // 发送一个字节
                while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);               
                return (ch);
}

/* 重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数 */
int fgetc(FILE *f)
{
                while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);  // 等待串口输入数据
                return (int)USART_ReceiveData(DEBUG_USARTx);
}
bsp_usart.h


#ifndef __BSP_USRT_H
#define __BSP_USRT_H

#include "stm32f10x.h"
#include <stdio.h>  // c语言库函数

// 条件编译
// 当我们使用哪一个串口时,把相应宏设置为1,其余为0,相当于开关
#define  DEBUG_USART1                1
#define  DEBUG_USART2                0
#define  DEBUG_USART3                0
#define  DEBUG_USART4                0
#define  DEBUG_USART5                0

#if DEBUG_USART1
// 串口1-USART1(APB2)
#define  DEBUG_USARTx                   USART1
#define  DEBUG_USART_CLK                RCC_APB2Periph_USART1
#define  DEBUG_USART_APBxClkCmd         RCC_APB2PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)  // PA9、PA10
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
   
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_9
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_10

#define  DEBUG_USART_IRQ                USART1_IRQn
#define  DEBUG_USART_IRQHandler         USART1_IRQHandler

#elif DEBUG_USART2

// 串口2-USART2
#define  DEBUG_USARTx                   USART2
#define  DEBUG_USART_CLK                RCC_APB1Periph_USART2
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOA)  // PA2、PA3
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
   
#define  DEBUG_USART_TX_GPIO_PORT       GPIOA   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_2
#define  DEBUG_USART_RX_GPIO_PORT       GPIOA
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_3

#define  DEBUG_USART_IRQ                USART2_IRQn
#define  DEBUG_USART_IRQHandler         USART2_IRQHandler

#elif DEBUG_USART3

// 串口3-USART3
#define  DEBUG_USARTx                   USART3
#define  DEBUG_USART_CLK                RCC_APB1Periph_USART3
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOB)  // PB10、PB11
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
   
#define  DEBUG_USART_TX_GPIO_PORT       GPIOB   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_10
#define  DEBUG_USART_RX_GPIO_PORT       GPIOB
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_11

#define  DEBUG_USART_IRQ                USART3_IRQn
#define  DEBUG_USART_IRQHandler         USART3_IRQHandler

#elif DEBUG_USART5

// 串口4-UART4
#define  DEBUG_USARTx                   UART4
#define  DEBUG_USART_CLK                RCC_APB1Periph_UART4
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOC)  // PC10、PC11
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
   
#define  DEBUG_USART_TX_GPIO_PORT       GPIOC   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_10
#define  DEBUG_USART_RX_GPIO_PORT       GPIOC
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_11

#define  DEBUG_USART_IRQ                UART4_IRQn
#define  DEBUG_USART_IRQHandler         UART4_IRQHandler

#elif DEBUG_USART5

// 串口5-UART5
#define  DEBUG_USARTx                   UART5
#define  DEBUG_USART_CLK                RCC_APB1Periph_UART5
#define  DEBUG_USART_APBxClkCmd         RCC_APB1PeriphClockCmd
#define  DEBUG_USART_BAUDRATE           115200

// USART GPIO 引脚宏定义
#define  DEBUG_USART_GPIO_CLK           (RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD)  // PC12、PD2
#define  DEBUG_USART_GPIO_APBxClkCmd    RCC_APB2PeriphClockCmd
   
#define  DEBUG_USART_TX_GPIO_PORT       GPIOC   
#define  DEBUG_USART_TX_GPIO_PIN        GPIO_Pin_12
#define  DEBUG_USART_RX_GPIO_PORT       GPIOD
#define  DEBUG_USART_RX_GPIO_PIN        GPIO_Pin_2

#define  DEBUG_USART_IRQ                UART5_IRQn
#define  DEBUG_USART_IRQHandler         UART5_IRQHandler

#endif

void USART_Config(void);  // 初始化
void Usart_SendByte(USART_TypeDef* pUSARTx, uint8_t data);  // 发送一个字节函数
void Usart_SendHalfWord(USART_TypeDef* pUSARTx, uint16_t data);  // 发送两个字节数据
void Usart_SendArray(USART_TypeDef* pUSARTx, uint8_t *array, uint8_t num);  // 发送n位数据的数组
void Usart_SendStr(USART_TypeDef* pUSARTx, uint8_t *str);  // 发送字符串

#endif /* __BSP_USART_H */

stm32f10x_it.c

// 串口中断服务函数
void DEBUG_USART_IRQHandler(void)
{
        LED_RED;  // 检测是否进入中断
        if(USART_GetITStatus(DEBUG_USARTx,USART_IT_RXNE)!=RESET)  // 检测标志位是否真正置1,以免产生误中断
        {               
                ucTemp = USART_ReceiveData(DEBUG_USARTx);
    USART_SendData(DEBUG_USARTx,ucTemp);   
        }         
}

stm32f10x_it.h
extern uint8_t ucTemp;  // 全局变量存储接收到的数据
野火论坛202307191026302245..png
回复

使用道具 举报

发表于 2023-7-19 17:07:57 | 显示全部楼层
搞个stlink或者jlink之类,加个断点,一下就知道有没有进;然后也可以在主循环打印信息,看uctemp值
回复 支持 反对

使用道具 举报

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

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-23 02:52 , Processed in 0.030791 second(s), 26 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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