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

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

当你看下面的代码时,它应该只运行一次,但是它永远在终端中重复,就像in t 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循环条件文本[I]!='\0',我用'\0'来停止在char[]结尾的循环,但是我假设'\0'意味着一个char=NULL当要真正满足条件时,实际上必须有一个='\0'。
虽然没有答案能抓住这一点,但我要感谢所有花时间帮助我解决这一问题的人,我投了你们所有人的票,因为你们的答案有助于我对整个C的理解,因为我有机会把一个问题标为答案,所以我要把“gmch”的答案标为他对变量数组和指向所述变量的指针数组之间的差异的解释,在我看来,这是一个极好的解释:)。

最佳答案

int* readings[3] = {0,0,0};是指向整数的指针数组。。。这可能就是为什么你要停止编译器对你的抱怨。
我看不到一个(int)readings[1]所以看不到它将如何处理getOutput(),但是如果它想要一个指向int的指针数组,那么您将给它三个0指针——这可能是不好的。
如其他地方所述,getOutput(readings)类似地是指向char *temp[40]的指针数组,而不是40个字符的数组。
当涉及到数组和指针时,C非常令人困惑,尤其是因为数组的名称隐式地是指向数组第一个元素的指针,并且(相反地)指针可以像数组一样使用。而“字符串”只是增加了混乱。所以在。。。

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

我们有一个由三个整数组成的数组,如图所示被初始化为char,还有一个指向整数“p”的指针,没有值。现在:
readings[2] += 1 ;

将1添加到readings生成readings[2]。我们可以:
p = readings ;

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

你可以说得更清楚。。。并符合:
p = &readings[1] ;

有趣的是,你可以写:
p[1] += 1 ;

('cos指针和数组在很大程度上是可交换的),这将把readings[0]设置为'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) ;

而在函数本身中,readings[2]a[2]*(a+2)z[2]几乎是可互换的。
通常我会想到一个定义:
字符条[22];
创建名为*(z+2)char*(伪)指针,该指针隐式指向22个字符数组的第一个元素。如果我还创建:
char* pc = bar ;

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

07-26 09:40