繁体   English   中英

int main没有明显原因循环吗? (PIC编程,XC16,MPLAB)dsPIC33EP

[英]int main is looping for no apparent reason? (PIC programming, XC16, MPLAB) dsPIC33EP

使用XC16编译器和MPLABX v2.10 IDE在dcPIC33上运行程序(显然用c编码)。 我实现了一些功能,其中一个功能是将文本字符串发送到uart,以便我可以使用串行终端查看串行输出。 我的问题在此行中找到。

UART_Write_Text("Starting ADXL345 test...fdsbjugbbjkdsf");

当您查看下面的代码时,该代码应该只运行一次,但是它将在终端中永远重复,就像int main fer循环一样,即使main在底部有一个while循环以防止其结束我也看不到它如何设法像这样循环。

    /* 
 * File:   main2.c
 * Author: nedu
 *
 * Created on 14 July 2014, 15:57
 */
#include <xc.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#if __XC16_VERSION < 1011
#warning "Please upgrade to XC16 v1.11 or newer."
#endif

#pragma config ICS = PGD3           // ICD Communication Channel Select bits (Communicate on PGEC3 and PGED3)
#pragma config JTAGEN = OFF         // JTAG Enable bit (JTAG is disabled)

// FPOR
#pragma config ALTI2C1 = OFF        // Alternate I2C1 pins (I2C1 mapped to SDA1/SCL1 pins)
#pragma config ALTI2C2 = OFF        // Alternate I2C2 pins (I2C2 mapped to SDA2/SCL2 pins)
#pragma config WDTWIN = WIN25       // Watchdog Window Select bits (WDT Window is 25% of WDT period)

// FWDT
#pragma config WDTPOST = PS32768    // Watchdog Timer Postscaler bits (1:32,768)
#pragma config WDTPRE = PR128       // Watchdog Timer Prescaler bit (1:128)
#pragma config PLLKEN = ON          // PLL Lock Enable bit (Clock switch to PLL source will wait until the PLL lock signal is valid.)
#pragma config WINDIS = OFF         // Watchdog Timer Window Enable bit (Watchdog Timer in Non-Window mode)
#pragma config FWDTEN = OFF         // Watchdog Timer Enable bit (Watchdog timer enabled/disabled by user software)

// FOSC
#pragma config POSCMD = NONE          // Primary Oscillator Mode Select bits (XT Crystal Oscillator Mode)
#pragma config OSCIOFNC = OFF       // OSC2 Pin Function bit (OSC2 is clock output)
#pragma config IOL1WAY = OFF        // Peripheral pin select configuration (Allow multiple reconfigurations)
#pragma config FCKSM = CSECMD       // Clock Switching Mode bits (Clock switching is enabled,Fail-safe Clock Monitor is disabled)

// FOSCSEL
#pragma config FNOSC = FRC          // Oscillator Source Selection (Internal Fast RC (FRC))
#pragma config IESO = OFF           // Two-speed Oscillator Start-up Enable bit (Start up with user-selected oscillator source)

// FGS
#pragma config GWRP = OFF           // General Segment Write-Protect bit (General Segment may be written)
#pragma config GCP = OFF            // General Segment Code-Protect bit (General Segment Code protect is Disabled)

#define FP 40000000
#define BAUDRATE 9600
#define BRGVAL ((FP/BAUDRATE)/16)-1
#define DELAY_105uS asm volatile ("REPEAT, #4201"); Nop(); // 105uS delay

unsigned int i;
char *temp[40];

#include "spi.h"
#include "ADXL345.h"

void delay_ms(long ms){
    unsigned long x = 0;
    for(x = 0; x <= ((FP/24000))*ms; x++)
        Nop();
}
void __attribute__((__interrupt__)) _U1TXInterrupt(void)
{
    IFS0bits.U1TXIF = 0; // Clear TX Interrupt flag
}

void UART_Write(char data)
{
    while(!U1STAbits.TRMT);
    U1TXREG = data;
}

void UART_Write_Text(char *text)
{
    int i;
    UART_Write('\n');
    UART_Write('\r');
    for(i=0;text[i]!='\0';i++)
        UART_Write(text[i]);
}

void InitClock(){
    PLLFBD=63; // M=65
    CLKDIVbits.PLLPOST=0; // N2=2
    CLKDIVbits.PLLPRE=1; // N1=3
    // Initiate Clock Switch to FRC oscillator with PLL (NOSC=0b001)
    __builtin_write_OSCCONH(0x01);
    __builtin_write_OSCCONL(OSCCON | 0x01);
    // Wait for Clock switch to occur
    while (OSCCONbits.COSC!= 0b001);
    // Wait for PLL to lock
    while (OSCCONbits.LOCK!= 1);
}

void InitUart(){
    U1MODEbits.STSEL = 0; // 1-Stop bit
    U1MODEbits.PDSEL = 0; // No Parity, 8-Data bits
    U1MODEbits.ABAUD = 0; // Auto-Baud disabled
    U1MODEbits.BRGH = 0; // Standard-Speed mode
    U1BRG = BRGVAL; // Baud Rate setting for 9600
    U1STAbits.UTXISEL0 = 0; // Interrupt after one TX character is transmitted
    U1STAbits.UTXISEL1 = 0;
    IEC0bits.U1TXIE = 1; // Enable UART TX interrupt
    RPOR4bits.RP43R = 1;    //RP43/RB11 as U1TX
    RPINR18bits.U1RXR = 42; //RP42/RB10 as U1RX
    U1MODEbits.UARTEN = 1; // Enable UART
    U1STAbits.UTXEN = 1; // Enable UART TX
    /* Wait at least 105 microseconds (1/9600) before sending first char */
    DELAY_105uS
}

int main(void)
{
    InitClock();
    InitUart();

    spi_init();
    UART_Write_Text("Starting ADXL345 test...fdsbjugbbjkdsf");
    enable_adxl345();
    int id = adxl345_devID();
    sprintf(temp, "Device ID is: 0x%02x", id);
    UART_Write_Text(temp);
    UART_Write_Text("Done");


    /*
    //Go into standby mode to configure the device.
    setPowerControl(0x00);

    //Full resolution, +/-16g, 4mg/LSB.
    setDataFormatControl(0x0B);

    //3.2kHz data rate.
    setDataRate(ADXL345_3200HZ);

    //Measurement mode.
    setPowerControl(0x08);
    */
    int* readings[3] = {0,0,0};
    getOutput(readings);
    int inter = 7;

    while(1)
    {
        delay_ms(1000);
        /*UART_Write_Text("Starting ADXL345 test...");*/
        sprintf(temp, "%i, %i, %i", inter, (int) readings[1], (int) readings[2]);
        UART_Write_Text("WORK");
    }
    return 0;
}

收到终端输出

我只是想不通,希望有人能指出我正确的方向?

更新:设法解决了我的问题,程序崩溃的原因是函数UART_Write_Text()中的for循环(下面注释掉了一个)。

void UART_Write(char data)
{
    while(!U1STAbits.TRMT);
    U1TXREG = data;
}

void UART_Write_Text(char *text)
{
    int i;
    UART_Write('\n');
    UART_Write('\r');

    for(i=0;i<25;i++)
        UART_Write(text[i]);
    /*
    for(i=0;text[i]!='\0';i++)
        UART_Write(text[i]);
    */
}

for循环条件text [I]!='\\ 0',我使用'\\ 0'在char []的末尾停止循环,但是我假设'\\ 0'表示当为了实际满足条件,实际上必须='\\ 0'。

尽管没有答案能解决这个问题,但我要感谢所有花时间尝试帮助我解决此问题的人,由于所有的答案都有助于我对C的整体理解,因此我向大家表示赞赏。在我看来,将一个问题标记为已回答的问题将要标记为“ gmch”的答案,因为他对变量数组与指向该变量的指针数组之间的区别的解释很出色:)。

您的代码中有未定义的行为 ,这将导致发生奇怪的事情(通常是崩溃)。

问题是您对变量temp定义以及如何使用它。 您可以在sprintf调用中将其用作字符串,但是将其定义为字符串数组

int* readings[3] = {0,0,0}; 是一个指向整数的指针数组……这可能就是为什么您(int)readings[1]阻止编译器向您抱怨。

我看不到getOutput()所以看不到它将对getOutput(readings)做什么,但是如果它想要一个指向int的指针数组,那么您可以给它三个0指针-这可能是不好的。

如其他地方所述, char *temp[40]类似地是指向char的指针数组,而不是40个char的数组。


对于数组和指针,C感到莫名其妙,这不仅是因为数组的名称隐式是指向数组第一个元素的指针,而且(相反)可以像使用数组一样使用指针。 而“字符串”只会增加混乱。 所以在...

int readings[3] = { 11, 22, 33 } ;
int* p ;

我们有一个由三个整数组成的数组,称为readings (如图所示),还有一个指向没有值的整数“ p”的指针。 现在:

readings[2] += 1 ;

readings[2]使得23 我们可以:

p = readings ;

所以现在p指向readings[0] -因为数组的名称自动地像指向数组开头的指针一样工作。 我们还可以写:

p = &readings[0] ;

您可以说的更清楚...并且与以下内容一致:

p = &readings[1] ;

有趣的是,您可以编写:

p[1] += 1 ;

(“ cos指针和数组在很大程度上是可互换的),这会将readings[2]设置为“ 33”。

实际上,以下所有内容均指readings[2]

*(p+1) 
p[1]
readings[2]
*(readings+2)

它会变得更好...当(显然)将数组传递给函数时,实际上是在将指针传递给数组的第一个元素。 因此,您的功能可以是:

static void foo(int* z) .....
static void foo(int a[]) .....

效果是一样的 您可以称之为:

foo(readings) ;
foo(p) ;

在函数本身中, a[2] *(a+2) z[2] *(z+2)几乎可以互换。

通常,我想到一个定义:

char bar [22];

就像创建一个称为barchar* (伪)指针一样,它隐式指向22个chars数组的第一个元素。 如果我还创建:

char* pc = bar ; 

然后创建一个(实际)指针,该指针也初始化为指向22个字符的数组的第一个元素。 barpc之间的区别很小:(1)您不能分配给bar它实际上是const (2) sizeof(bar)给出数组的大小,而sizeof(pc)给出指针的大小。

作为一般建议:将程序分成几部分,将整个数除以2,或者按函数排除函数(调用)。 大概从简单循环开始, usngined long i = 0; while (1) { printf("%x ",i); i++; } usngined long i = 0; while (1) { printf("%x ",i); i++; } usngined long i = 0; while (1) { printf("%x ",i); i++; }为了确保看门狗定时器pragma应用。 然后排除其他人。 否则,您只能分析代码和文档。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM