2014-04-10 4 views
1

저는 C 프로그래밍 및 마이크로 컨트롤러를 처음 사용합니다. C18과 함께 PIC18F24K20 마이크로 컨트롤러를 사용하고 있습니다. 나는 USART 전송 및 수신 기능을 사용하여 컴퓨터 입력으로부터 정보를 수신하도록 설정했습니다. 나의 목표는 수신 된 단어를 알려진 단어와 비교하고 어떤 단어를 받았는지에 따라 컴퓨터로 다시 전송하는 것입니다. 아래는 관련 코드입니다.C18 함수에 문자 배열 전달

#include "p18f24k20.h" 
#include "delays.h" 
#include "string.h" 
#include "stdlib.h" 


void CommTransmit (rom char *); 

void main (void) 
{ 
    char buf[11], data, T; 
    int i; 

    i = 0; 
    memset(buf, 0, sizeof buf); 

    while(1) 
    { 
     if (PIR1bits.RCIF) 
     { 
      data = USART_receive(); 
      if (data != 47)    // 47 is /, indicates end of string 
      { 
       buf[i] = data; 
       i++; 
      } 
      else 
      { 
       // T = strcmppgm2ram(buf,(const far rom char*)"test"); 
       CommTransmit(buf); 
       USART_transmit('t'); 
       buf[0] = 0' 
      } 
     } 
    } 
} 


void CommTransmit (rom char *CommVariable) 
{ 
    char test; 

    test = strcmppgm2ram(CommVariable, (const far rom char*)"test"); 
    if (test == 0) 
    { 
     USART_transmit('g'); 
    } 
} 

코드는 현재 무엇이 잘못되었는지를 테스트하기 위해 테스트하도록 설정되어 있습니다. 컴퓨터를 실행하면 마이크로 컨트롤러가 CommTransmit 기능을 실행 한 것처럼 't'가 표시됩니다. 그러나 결코 'g'를 전송하지 않습니다. if 문 밖에서 CommTransmit 함수에 USART_transmit ('g') 호출을 넣었더라도 strcmppgm2ram 함수에서 멈추는 것처럼 호출되지는 않지만 여전히 't'를 전송합니다.

CommTransmit 함수에서 중단하고 한 줄씩 실행하면 제대로 작동하는 것 또한 이상합니다. 그러나 CommVariable을 MPLAB IDE 내부에서 보면, 그 함수가 호출되기 전에 'buf'변수가 올바르지 만 실제로는 그럴 수 없습니다. CommVariable의 가치는 배열의 크기에 따라 다릅니다.

독서에서 나는 마이크로 컨트롤러가 변수 (프로그램 대 데이터 메모리?)를 저장하는 방법으로 인해 발생할 수 있다고 생각하지만 확실하지 않습니다. 어떤 도움이라도 대단히 감사합니다!

편집 : CommTransmit 줄 앞에 else 문에서 T = strcmppgm2ram 줄의 주석을 제거하면 제대로 작동합니다 (두 문자열이 같을 때 T = 0). strcmppgm2ram 함수가 제대로 작동하지 않게하는 함수를 통해 배열을 전달하면 배열이 변경된다고 생각합니다.

+0

안녕하세요. 나는 C18에서 프로그래밍하지 않았다 (그러나 다른 임베디드 시스템에서 가지고있다). 하지만''const far rom char * ' "test"'에 대해서는 의심 스럽습니다. 문자열 리터럴이 메모리의 오른쪽 영역에 없다면이 캐스트는 그것을 이동하지 않고 가짜 포인터를 보냅니다. 캐스트없이 어떻게됩니까? –

+0

BTW는'data! = 47' 케이스에서'i <11'을 확인합니다. –

+1

무작위적인 동작을 감안할 때, 어딘가에 메모리 관련 버그가있는 것처럼 들립니다. 일부 포인터 또는 배열 버그로 인해 strcmppgm2ram()에서 메모리가 손상되었습니다. 그것은 사용자 정의 함수 또는 일부 라이브러리입니까? 또한 이것은 PIC이므로 스택 오버플로는 항상 가능성있는 후보입니다. – Lundin

답변

1

strcmppgm2ram 이해가 안

signed char strcmppgm2ram(const char * str1, const rom char * str2); 

에 대한 서명을 보면 왜 CommVariable는 에 대한 롬 문자 *이 없습니다.

PICmicro 칩의 마이크로 컨트롤러는 별도의 프로그램 메모리와 자신의 디자인 데이터 메모리 주소 버스를 사용하기 때문에 MPLAB® C18 C Compiler User’s Guide이, MPLAB C18은 프로그램 메모리에있는 데이터를 구분하는 확장을 필요로 장 2.4.3 RAM/ROM 예선에서 및 데이터 메모리에있는 데이터를 포함 할 수있다./---/포인터는 데이터 메모리 (램 포인터) 또는 프로그램 메모리 (rom 포인터)를 가리킬 수 있습니다. 이 rom로 선언되지 않으면 포인터가 램 포인터로 간주됩니다.

그리고 2.7.3 문자열 상수에서 :

MPLAB C18 에 대한 별도의 주소 공간의 중요한 결과는

그 데이터의 데이터에 프로그램 메모리에있는 데이터와 포인터에 대한 포인터 메모리가 호환되지 않습니다./---/그들은 서로 다른 주소 공간을 참조하기 때문에 입니다./---/ MPLAB C18은 자동으로 모든 문자열 상수를 프로그램 메모리에 저장합니다. 이 문자열 상수 유형은 " 메모리에있는 char 배열", (const rom char [])입니다.

그리고 또한 두 번째 인수에 대해 const를 훨씬 롬 문자 *로 타입 캐스팅의 목적을 분명하지 않다. 멀리 포인터가 더 큰 크기 (24 비트) 때문에 스택 손상이 발생할 수 있습니다. 따라서 다음과 같이 다시 써야합니다.

void CommTransmit (const char *CommVariable) 
{ 
    if (!strcmppgm2ram(CommVariable, "test")) { 
     USART_transmit('g'); 
    } 
}