Mdy912 2024-04-21 20:30 采纳率: 0%
浏览 22

stm32配合RFID读取卡号

代码有什么问题码,哪里有问题啊,懵了,给看看


#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
#include "stdio.h"

static GPIO_InitTypeDef      GPIO_InitStructure;
static USART_InitTypeDef     USART_InitStructure;
static NVIC_InitTypeDef     NVIC_InitStructure;        



//重定义fputc函数 
int fputc(int ch, FILE *f)
{     
    USART_SendData(USART1,ch);
    while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);  
    
    return ch;
}   

void delay_us(uint32_t nus)
{        
    uint32_t temp;             
    SysTick->LOAD =SystemCoreClock/8/1000000*nus;     //时间加载               
    SysTick->VAL  =0x00;                            //清空计数器
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;         //使能滴答定时器开始倒数      
    do
    {
        temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16)));            //等待时间到达   
    SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;         //关闭计数器
    SysTick->VAL =0X00;                               //清空计数器 
}

void delay_ms(uint16_t nms)
{                     
    uint32_t temp;           
    SysTick->LOAD=SystemCoreClock/8/1000*nms;        //时间加载(SysTick->LOAD为24bit)
    SysTick->VAL =0x00;                               //清空计数器
    SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;        //能滴答定时器开始倒数 
    do
    {
        temp=SysTick->CTRL;
    }while((temp&0x01)&&!(temp&(1<<16)));            //等待时间到达   
    SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;        //关闭计数器
    SysTick->VAL =0X00;                               //清空计数器              
} 


void USART1_Init(uint32_t baud)
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);                             //使能GPIOA时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);                            //使能USART1时钟
 
    //串口1对应引脚复用映射
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);                         //GPIOA9复用为USART1
    GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);                         //GPIOA10复用为USART1
    
    //USART1端口配置
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;                         //GPIOA9与GPIOA10
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;                                    //复用功能
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;                                //速度50MHz
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;                                     //推挽复用输出
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;                                     //上拉
    GPIO_Init(GPIOA,&GPIO_InitStructure);                                             //初始化PA9,PA10

    //USART1 初始化设置
    USART_InitStructure.USART_BaudRate = baud;                                        //波特率设置
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;                        //字长为8位数据格式
    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(USART1, &USART_InitStructure);                                         //初始化串口1
    
    USART_Cmd(USART1, ENABLE);                                                      //使能串口1 
    
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);                                    //开启相关中断

    //Usart1 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;                                //串口1中断通道
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=5;                            //抢占优先级3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority =5;                                //子优先级3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                    //IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);                                                    //根据指定的参数初始化VIC寄存器
}


void USART3_Init(uint32_t baud)
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    /* GPIOB Configuration: PB10 PB11 */
    GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10 | GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;        
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    /* Connect USART3_TX pins to PB10 */
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
    
    /* Connect USART3_RX pins to PB11 */
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);

    /* Enable USART3 clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    
    USART_InitStructure.USART_BaudRate = baud;                                    
    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);

     
    /* Enable the USARTx Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
     
    /* Enable USART3 */
    USART_Cmd(USART3, ENABLE);
    
    /* Enable the Rx buffer empty interrupt */
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
}


//"AT+NAMEGECBLE\r\n"
void USART3_String(char *string)
{
    printf("send string=%s\n", string);
    
    while(*string != '\0')
    {
        //发送数据
        USART_SendData(USART3,*string);
            
        while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);
        
        string++;
    }

}
void USART3_SendBytes(volatile uint8_t *pbuf,uint32_t len)
{

    while(len--)
    {
        USART_SendData(USART3,*pbuf++);
        while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);     
    }

}
// 计算校验和函数
unsigned char BCC_function(unsigned char* data, int length) {
    unsigned char bcc = 0;
    for (int i = 0; i < length; i++) {
        bcc ^= data[i];
    }
    return bcc;
}

// 发送请求命令函数
void send_request_command() {
    unsigned char buf_request[7];
    buf_request[0] = 0x07;      // 数据帧长度
    buf_request[1] = 0x02;      // 命令类型
    buf_request[2] = 'A';       // 命令 'A'
    buf_request[3] = 0x01;      // 数据长度
    buf_request[4] = 0x52;      // 信息
    buf_request[5] = BCC_function(buf_request, 5); // 校验和
    buf_request[6] = 0x03;      // 结束符

    USART3_SendBytes(buf_request, 7); // 发送请求命令数据
}

// 发送防碰撞命令函数
void send_collision_avoidance_command() {
    unsigned char buf_cmd[8];
    buf_cmd[0] = 0x08;                  // 数据帧长度
    buf_cmd[1] = 0x02;                  // 命令类型
    buf_cmd[2] = 'B';                   // 命令 'B'
    buf_cmd[3] = 0x02;                  // 数据长度
    buf_cmd[4] = 0x93;                  // 信息
    buf_cmd[5] = 0x00;                  // 信息
    buf_cmd[6] = BCC_function(buf_cmd, 6); // 校验和
    buf_cmd[7] = 0x03;                  // 结束符

    USART3_SendBytes(buf_cmd, 8); // 发送防碰撞命令数据
}
int main(void)
{ 
    

    //系统定时器初始化,时钟源来自HCLK,且进行8分频,
    //系统定时器时钟频率=168MHz/8=21MHz
    SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 
        
    
    //串口1,波特率115200bps,开启接收中断
    USART1_Init(115200);
    USART3_Init(9600);
    //delay_ms(500);
  // 发送请求命令
  send_request_command();

  // 发送防碰撞命令
  send_collision_avoidance_command();
    while(1)
    {
         send_request_command();
        delay_ms(2000);
  // 发送防碰撞命令
  send_collision_avoidance_command();
    }
}

static volatile uint8_t g_usart1_recv_buf[128]={0};
static volatile uint8_t g_usart1_recv_cnt = 0;



//void USART3_SendBytes(volatile uint8_t *pbuf,uint32_t len)
//{

//    while(len--)
//    {
//        USART_SendData(USART3,*pbuf++);
//        while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);     
//    }

//}

void USART1_IRQHandler(void)                                //串口1中断服务程序
{
    

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)      //接收中断
    {
        //从串口1接收数据
        g_usart1_recv_buf[g_usart1_recv_cnt]=USART_ReceiveData(USART1);    
        
        //记录多少个数据
        g_usart1_recv_cnt++;
        
        //检测到换行符或接收的数据满的时候则发送数据
        if(g_usart1_recv_buf[g_usart1_recv_cnt-1]=='\n')
        {
            
            USART3_SendBytes(g_usart1_recv_buf,g_usart1_recv_cnt);
            
            g_usart1_recv_cnt = 0;
        }
             
    } 

} 


void USART3_IRQHandler(void)                                //串口1中断服务程序
{
    uint8_t d;

    if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)      //接收中断
    {
        //printf("recv data\n");
        
        //接收数据
        d = USART_ReceiveData(USART3);                        
        
        //发送数据
        USART_SendData(USART1,d);
        
        while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
             
    } 

} 

img

img

img


为什么读取不了,也没反应

  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-21 20:30
    关注

    引自免费微信小程序:皆我百晓生

    这段代码的目标是实现STM32通过USART1和USART3两个串口与RFID模块通信。首先,让我们逐段分析代码,然后找出可能的问题并提供相应的解决方案。

    1. 包含头文件:这些头文件包含了你需要使用的STM32F4系列的GPIO、RCC、USART和中断相关的库函数。
    2. 重定义fputc():这个函数用于将字符输出到串口1,以便于打印调试信息。
    3. 延时函数delay_us()delay_ms() 分别用于微秒和毫秒级别的延时。
    4. USART1 和 USART3 初始化:这两个函数分别初始化USART1和USART3,设置波特率、数据格式等,并配置GPIO引脚。同时,它们还设置了中断处理程序。
    5. 发送字符串和字节函数USART3_String()USART3_SendBytes() 分别用于发送字符串和字节数组到USART3。
    6. 计算校验和函数BCC_function() 计算输入数组的异或和作为校验和。
    7. 发送请求和防碰撞命令函数send_request_command()send_collision_avoidance_command() 分别发送请求和防碰撞命令到USART3。
    8. 主函数:这里初始化了定时器、串口和中断,然后进入无限循环发送请求和防碰撞命令。
    9. 中断服务程序USART1_IRQHandler()USART3_IRQHandler() 分别处理USART1和USART3的接收中断。当接收到数据时,USART1_IRQHandler() 将数据保存到缓冲区并在检测到换行符后发送回USART3。

    问题分析及建议

    1. USART3_IRQHandler() 中的错误:在USART3_IRQHandler()中,每次接收到数据后,你都立即发送回USART1。这可能会导致数据丢失,因为USART1的发送操作可能还没有完成,而新的数据又已经开始接收。你应该在发送完当前缓冲区的数据后再接收新数据,可以添加一个标志位来控制这个流程。

      static volatile bool usart3_send_in_progress = false;
      
      void USART3_IRQHandler(void) {
          if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET && !usart3_send_in_progress) { // 只有在没有正在发送时才接收数据
              uint8_t d = USART_ReceiveData(USART3);
              usart3_send_in_progress = true;
              USART_SendData(USART1, d);
              while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
              usart3_send_in_progress = false; // 发送完成后标记为空闲
          }
      }
      
    2. 接收中断处理:目前的代码没有处理USART1中断中的数据处理逻辑,你可能需要在这里解析接收到的数据,判断是否符合预期的响应格式,以及执行相应的操作。例如,检查状态和UID大小字段,根据结果决定是否需要进一步的操作。

    3. 错误处理:确保在发送命令之前正确初始化了串口,包括波特率、数据格式等。另外,在发送命令后,应该检查命令是否成功发送,以及从机的响应是否正确。对于错误情况,可以考虑添加适当的日志输出或者异常处理机制。

    4. 中断优先级:在配置中断时,你可能需要调整中断优先级以确保正确的中断处理顺序。例如,如果你的USART1中断处理程序比USART3中断处理程序更频繁地被触发,那么USART3的中断可能会被延迟处理。

    5. 任务调度:在主循环中,你不断发送请求和防碰撞命令,这可能导致RFID模块无法及时响应。尝试增加一些间隔,允许RFID模块有足够的时间来处理命令和发送响应。

    6. 数据包完整性:确保你发送的数据包结构正确,包括帧长度、命令类型、命令、数据长度、信息、校验和和结束符。你也可以添加额外的错误检测措施,比如检查接收到的数据包是否完整。

    7. RFID模块兼容性:确认你的STM32与RFID模块之间的通信协议与提供的参考文档相匹配,包括波特率、数据格式、帧结构等。

    在进行修改之后,再次测试代码并观察串口通信是否正常。如果仍然存在问题,可能需要查看RFID模块的文档或使用示波器来检查实际的物理层通信情况。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 4月21日

悬赏问题

  • ¥20 数学建模来解决我这个问题
  • ¥15 计算机网络ip分片偏移量计算头部是-20还是-40呀
  • ¥15 stc15f2k60s2单片机关于流水灯,时钟,定时器,矩阵键盘等方面的综合问题
  • ¥15 YOLOv8已有一个初步的检测模型,想利用这个模型对新的图片进行自动标注,生成labellmg可以识别的数据,再手动修改。如何操作?
  • ¥30 NIRfast软件使用指导
  • ¥20 matlab仿真问题,求功率谱密度
  • ¥15 求micropython modbus-RTU 从机的代码或库?
  • ¥15 django5安装失败
  • ¥15 Java与Hbase相关问题
  • ¥15 后缀 crn 游戏文件提取资源