You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PIC16F877A+L293D直流电机控制器代码编译上传故障求助

PIC16F877A直流电机控制器代码问题修复方案

代码中的核心问题及修复:

  1. 配置位缺失/错误
    PIC16F877A必须通过配置位指定振荡器类型、看门狗、MCLR功能等参数,缺失配置或参数错误会直接导致编译失败或程序无法正常运行。

    • 修复:添加配置位定义(根据硬件调整,示例为HS振荡器、关闭看门狗):
      // 可放在代码开头或config.h中
      __CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & BOREN_ON & LVP_OFF & CPD_OFF & WRT_OFF & DEBUG_OFF);
      
  2. IO端口操作不规范
    单独操作TRISD0、TRISD1的写法不兼容部分PIC编译器,需通过TRISD寄存器整体配置端口方向。

    • 修复:替换原IO配置代码:
      // 原代码:TRISD0 = 0; TRISD1 = 0;
      TRISD &= ~0x03; // 将RD0、RD1设置为输出
      
  3. PWM占空比位操作错误
    设置CCP1X位时,直接使用DC & 2会将位值设为2(二进制10),但CCP1X是单个位寄存器,只能取0或1,导致占空比计算错误。

    • 修复:修正PWM1_Set_Duty函数中的位操作:
      void PWM1_Set_Duty(uint16_t DC)
      {
        if(DC < 1024)
        {
          CCP1Y = DC & 1;          // 取DC的第0位
          CCP1X = (DC >> 1) & 1;   // 取DC的第1位
          CCPR1L = DC >> 2;        // 取DC的高8位
        }
      }
      
  4. CCP模块配置不完整
    仅设置CCP1M3和CCP1M2无法完全启用PWM模式,需将CCP1M1和CCP1M0设为0。

    • 修复:用CCP1CON寄存器一次性配置:
      // 原代码:CCP1M3 = 1; CCP1M2 = 1;
      CCP1CON = 0x0C; // CCP1M3=1, CCP1M2=1, 其余位0,启用PWM模式
      
  5. 按钮消抖与电平稳定性问题
    原代码仅通过延迟等待按钮释放,未做消抖检测,且未启用RB端口内部上拉,导致按钮易受干扰、误触发。

    • 修复:启用RB内部上拉,并添加按钮释放检测:
      // 在main函数开头添加
      OPTION_REG &= ~0x80; // 清除RBPU位,启用RB端口内部上拉
      
      修改按钮检测逻辑(以Rev按钮为例):
      if(Rev)
      {
        __delay_ms(20); // 消抖延迟
        while(Rev);     // 等待按钮释放
        RD0 = ~RD0;
        RD1 = ~RD1;
      }
      
      其余按钮检测同理修改,避免一次按下多次触发。
  6. 冗余代码问题
    main函数为void类型,末尾的return;语句无意义,可删除。


修复后的完整代码:

#include <xc.h>
#include <stdint.h>

// 配置位定义(根据硬件调整)
__CONFIG(FOSC_HS & WDTE_OFF & PWRTE_ON & BOREN_ON & LVP_OFF & CPD_OFF & WRT_OFF & DEBUG_OFF);

#define _XTAL_FREQ 4000000

// 引脚定义
#define Rev RB0   // 反转按钮
#define LV0 RB1   // 0%速度按钮
#define LV1 RB2   // 50%速度按钮
#define LV2 RB3   // 75%速度按钮
#define LV3 RB4   // 100%速度按钮

// 函数声明
void PWM1_Set_Duty(uint16_t);

void main(void)
{
  // IO端口配置
  TRISB = 0x1F;          // RB0-RB4设为输入
  TRISD &= ~0x03;        // RD0、RD1设为输出
  OPTION_REG &= ~0x80;   // 启用RB端口内部上拉

  // 初始方向:顺时针
  RD0 = 0;
  RD1 = 1;

  // CCP1 PWM配置
  CCP1CON = 0x0C;        // 启用PWM模式
  TRISC2 = 0;            // CCP1输出引脚(RC2)设为输出

  // Timer2配置(PWM频率2kHz)
  PR2 = 124;             // 周期寄存器设置
  T2CKPS0 = 1;
  T2CKPS1 = 0;           // Timer2预分频1:4
  TMR2 = 0;              // 初始化Timer2计数器
  TMR2ON = 1;            // 启动Timer2

  // 主循环
  while(1)
  {
    // 反转方向
    if(Rev)
    {
      __delay_ms(20);
      while(Rev);
      RD0 = ~RD0;
      RD1 = ~RD1;
    }
    // 0%占空比
    if(LV0)
    {
      __delay_ms(20);
      while(LV0);
      PWM1_Set_Duty(0);
    }
    // 50%占空比
    if(LV1)
    {
      __delay_ms(20);
      while(LV1);
      PWM1_Set_Duty(250);
    }
    // 75%占空比
    if(LV2)
    {
      __delay_ms(20);
      while(LV2);
      PWM1_Set_Duty(375);
    }
    // 100%占空比
    if(LV3)
    {
      __delay_ms(20);
      while(LV3);
      PWM1_Set_Duty(500);
    }
    __delay_ms(10);
  }
}

// PWM占空比设置函数
void PWM1_Set_Duty(uint16_t DC)
{
  if(DC < 1024)
  {
    CCP1Y = DC & 1;
    CCP1X = (DC >> 1) & 1;
    CCPR1L = DC >> 2;
  }
}

内容的提问来源于stack exchange,提问作者Abdou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 19:40:36