c - 与 PIC18F252 上的 ADC 输出作斗争

标签 c pic adc

我最近完成了 PIC18F252 的代码,它使用内置 ADC 将来自 3 个传感器的模拟输入转换为可发送到电机的数字输出。代码构建并上传到 PIC 的效果非常好,但不幸的是就是不起作用,我正在努力找出问题所在。 在测试了电机的输出端口后,我发现它们都输出相同的信号,而它们不应该输出,并且它不会根据传感器而改变。 我的第一个想法是 ADC 的输出(从 ADRESH 加载结果)和用于为这些输出分配数字值的 if 语句之间存在问题。 我无法上传整个代码,因为这是类(class)作业,但我已经添加了相关部分。我只包含了使用一个 channel 进行 AD 转换的函数,但其​​他两个 channel 的函数是相同的,只是更改了变量。

如果有人能够发现此代码的问题(大概是围绕 if 语句),我将不胜感激!

#include <p18F252.h> // PIC specific definitions
#include <xc.h> // Xc8 compiler specifics
#include <stdio.h> // Standard C I/O library
#include <stdlib.h> // Standard C library

// Function declarations
void Config_ADC(void);
void delay(void);
void Motor_Output(unsigned char x, unsigned char y, unsigned char z);
void channel3(void);

unsigned char leftSens = 0b00000000; //Initialise left sensor variable

void Config_ADC(void){
    // ADC Setup
    TRISA = 0xFF; // configure port A as inputs
    ADCON1bits.ADFM =0; // left justified
    ADCON1bits.PCFG3=0; 
    ADCON1bits.PCFG2=1;
    ADCON1bits.PCFG1=0; 
    ADCON1bits.PCFG0=0; 
    ADCON1bits.ADCS2=0;
    ADCON0bits.ADCS1=1;
    ADCON0bits.ADCS0=0; 
    ADCON0bits.ADON =1; 
}

// Function for a delay of 1ms
void delay(void){ 
    T2CON = 0x49; // start counting from 73
    PR2 = 0x7C; // stop count at 124
    T2CONbits.TMR2ON = 1; // activate timer 2
    while(!PIR1bits.TMR2IF); // wait for timer flag
    T2CONbits.TMR2ON = 0; // stop timer 2
    PIR1bits.TMR2IF = 0; // clear flag
}

void channel3(void){
    ADCON0bits.CHS2 = 0; //Channel selection
    ADCON0bits.CHS1 = 1;
    ADCON0bits.CHS0 = 1;
    delay(); // Acquisition time to charge hold capacitor
    ADCON0bits.GO_DONE = 1; // Start Conversion
    while(ADCON0bits.GO_DONE); // Wait for A/D Conversion to complete
    leftSens = ADRESH; // Return result
}

void main(void){
    TRISB = 0x00; // configure Port B as output
    Config_ADC(); // load ADC
    while(1) { //loop forever/
        channel3(); // Call channel 3 conversion
        Motor_Output(leftSens, middleSens, rightSens);
    }
}

// Function to send instructions to motors
void Motor_Output(unsigned char x, unsigned char y, unsigned char z){
    int left, middle, right;
    if(x >= 173){left = 1;}   //173 chosen as threshold 8 bit value
    else if(x < 173){left = 0;}
    else if(y >= 173){middle = 1;}
    else if(y < 173){middle = 0;}
    else if(z >= 173){right = 1;}
    else if(z < 173){right = 0;}

    unsigned char output;
    output = (left << 2) | (middle << 1) | right;  //Bit shifted variables into one value
    switch(output){
        case 0x0:
            PORTBbits.RB7 = 0; //Test for each output and activate motors accordingly
            PORTBbits.RB6 = 1;
            PORTBbits.RB5 = 0;
            PORTBbits.RB4 = 1;
        case 0x1:
            PORTBbits.RB7 = 0; 
            PORTBbits.RB6 = 1;
            PORTBbits.RB5 = 1;
            PORTBbits.RB4 = 0;
        case 0x2:
            PORTBbits.RB7 = 0; 
            PORTBbits.RB6 = 1;
            PORTBbits.RB5 = 0;
            PORTBbits.RB4 = 1;
        case 0x3:
            PORTBbits.RB7 = 0; 
            PORTBbits.RB6 = 1;
            PORTBbits.RB5 = 1;
            PORTBbits.RB4 = 0;
        case 0x4:
            PORTBbits.RB7 = 1; 
            PORTBbits.RB6 = 0;
            PORTBbits.RB5 = 0;
            PORTBbits.RB4 = 1;
        case 0x5:
            PORTBbits.RB7 = 0;
            PORTBbits.RB6 = 1;
            PORTBbits.RB5 = 0;
            PORTBbits.RB4 = 1;
        case 0x6:
            PORTBbits.RB7 = 1; 
            PORTBbits.RB6 = 0;
            PORTBbits.RB5 = 0;
            PORTBbits.RB4 = 1;
        case 0x7:
            PORTBbits.RB7 = 0; 
            PORTBbits.RB6 = 1;
            PORTBbits.RB5 = 0;
            PORTBbits.RB4 = 1; 
    }
    return;
}

最佳答案

如果不进行更深入的分析,有两个主要问题:

  1. if-else if链只会对left进行一次分配。为了使这一点显而易见,我以这种方式缩进了您的源代码,没有任何其他更改:

    if (x >= 173) {     // Either THIS...
        left = 1;
    } else
        if (x < 173) {  // Or THAT will be true.
            left = 0;
        } else          // None of the following is executed therefore.
            if (y >= 173) {
                middle = 1;
            } else
                if (y < 173) {
                    middle = 0;
                } else
                    if (z >= 173) {
                        right = 1;
                    } else
                        if (z < 173) {
                            right = 0;
                        }
    

    因此middleright将具有未定义的值。

  2. switch 中的所有 case 都缺少 break。因此,只有最后一个案例或根本不会被执行。为什么“没有”?由于 middleright 具有未定义的值,导致 output 中出现随机值。

    注意:“随机”可能始终是相同的值,具体取决于分别在中间位置设置或重置的位。

关于c - 与 PIC18F252 上的 ADC 输出作斗争,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59067179/

相关文章:

c - 如何在 mac os x 上基于 openGL 上下文创建 OpenCL 上下文

c++ - double 或浮点比较

c - 用C18读取pic18 rom常量

python - 使用 Sample count 或 time.time() 在 RasPi3 和 ADS1115 中进行采样

c - 如何将读取 ADC 值转换为 float ?

c - 如何用C写这个

c - 退出应用程序时 luaF_newproto 处的 Lua 5.1 段错误

c - 如何将 10 位值传递给两个寄存器?

c - 这是有效的代码吗?带有 @ 和地址标记的 extern,来自 PIC 微 Controller 库

c - STM32 ADC DMA。 MCU何时得知ADC结束?