2013-04-30 6 views
3

У меня есть новая проблема здесь. Я все еще изучаю C для PIC (компилятор xc8), и как начинающий проект, я делаю термометр с популярным ds18b20 и pic16f628, в котором я лежал. Моя программа действительно хорошо себя ведет, когда ей разрешено работать, но пока я играл с указателями, структурами, массивами и т. Д., Чтобы вернуть несколько значений в функцию, я заметил, что что-то пошло не так, и теперь компьютер идет туда и обратно, не позволяя программа запускается последовательно, по крайней мере, это то, что я вижу, если я использую симулятор в mplabx. Я совершенно уверен, что кое-что забыл о расположении программ и/или памяти, но я не могу понять, что и почему. Кто-нибудь может мне помочь? Я вставляю здесь основной код, что еще вам нужно?C для 16f628, счетчик программ идет haywire

/* 
* File: termometro.c 
* Author: zakkos 
* Created on April 18, 2013, 2:20 PM 
* 
*/
/*ESSENTIAL DEFINITIONS*/ 
#define _XTAL_FREQ 4000000 
/*INCLUSIONS*/ 
#include <xc.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <lcd.h> 
#include <1-wire.h> 
/*CONFIG PRAGMA*/ 
#pragma config BOREN = OFF, CPD = OFF, FOSC = INTOSCIO, MCLRE = OFF, WDTE = OFF, CP = OFF, LVP = OFF, PWRTE = ON 

//typedef unsigned char uint8_t; 

void read_temp(void); 

union { 
    char eratura; 
    char decimali; 
}temps; 

int main(void) { 

    INTCON = 0x00; 
    PIE1 = 0x00; 

    CMCON = 0x07; //disabilito i comparatori - disable comparators 

    TRISA = 0x00; 
    PORTA = 0x00; 

    TRISB = 0x00; 
    PORTB = 0x00; 

    const char decims[16] = {0, 0, 1, 1, 2, 3, 3, 4, 5, 5, 6, 6, 7, 8, 8, 9}; 
    char temp; 

    lcd_init(); 
    lcd_send_cmd(LCD_CLR); 
    lcd_send_cmd(LCD_HOME); 
    writeString("Hello,"); 
    lcd_send_cmd(LCD_LN2); 
    writeString("World!"); 
    __delay_ms(1000); 
    while(1) 
    { 
     read_temp(); 
     lcd_send_cmd(LCD_CLR); 
     lcd_send_cmd(LCD_HOME); 
     writeString("Temp:"); 
     lcd_send_cmd(LCD_LN2); 
     if((temps.eratura & 0x80)){        //if sign bit is set 
       temps.eratura = ~temps.eratura;     //2's complement 
       temps.eratura += 1;        
       temps.decimali = ~temps.decimali;    //2's complement 
       temps.decimali += 1; 
       lcd_send_dat(0x2D);        //minus 
     } 
     temp = (temps.eratura/100)& 0x0F;      //centinaia 157/100=1 (hundreds) 
     if(temp){ 
      lcd_send_dat(0x30 | temp); 
      temp = ((temps.eratura/10)%10) & 0x0F;    //decine 157/10=15%10=5 (tens if hundreds is set, meaning it will display also a 0) 
      lcd_send_dat(0x30 | temp); 
     } else { 
      temp = ((temps.eratura/10)%10) & 0x0F;    //decine 157/10=15%10=5 (tens if hundreds is no set, meaning it will not display if 0) 
      if(temp){lcd_send_dat(0x30 | temp); 
      } 
     } 
     lcd_send_dat(0x30 | (temps.eratura%10)& 0x0F);   //unita  157%10=7 (ones) 
     lcd_send_dat(0x2E);          //dot 
     lcd_send_dat(0x30 | decims[temps.decimali] & 0x0F);  //decimals 
     lcd_send_dat(0xDF);          //degrees 
} 
} 

void read_temp(void){ 
    char scratchpad[9]; 
    while(ow_reset()); 
    ow_write_byte(0xCC); 
    ow_write_byte(0x44); 
    while(ow_read_bit()==0); 
    __delay_ms(1); 
    while(ow_reset()); 
    ow_write_byte(0xCC); 
    ow_write_byte(0xBE); 
    for(char k=0;k<10;k++){ 
     scratchpad[k] = ow_read_byte(); 
    } 
    temps.decimali = scratchpad[0] & 0x0F; 
    temps.eratura = (scratchpad[1] << 4)|(scratchpad[0] >> 4); 
    return; 
} 
+1

Не уверен, что stackoverflow - это лучшее место для публикации. У вас может быть больше шансов: http://electronics.stackexchange.com/ – joce

+0

Спасибо, я попробую! – zakkos

+0

Также попробуйте http://www.microchip.com/forums/, хотя здесь есть некоторые многообещающие ответы. –

ответ

1

На форуме с микрочипом они обнаружили недостаток кода. Оказывается, проблема была, я не учитывал отрицательный индекс в decims[]; массиве, когда он был оценен в случае отрицательной температуры

if(temps.eratura < 0){ 
temps.eratura = -temps.eratura; 
temps.decimali = -temps.decimali; 
lcd_send_dat('-'); 
} 

затем используется в

lcd_send_dat(decims[temps.decimali]); //decimals 

2-х дополнение байта, содержащего только нижний полубайт (0x0F), имеет самый значительный набор полубайтов (0xF1). Это стало причиной всех моих проблем! Добавление маски на нижней клев после дополнения байт решить проблему:

if(temps.eratura < 0){ 
temps.eratura = -temps.eratura; 
temps.decimali = -temps.decimali & 0x0F; 
lcd_send_dat('-'); 
} 

Спасибо всем за ответы, вы действительно помогли мне понять, как это работает!

6
for(char k=0;k<10;k++){ 
    scratchpad[k] = ow_read_byte(); 
} 

... будет работать с 0-9 (10 символов), а ...

char scratchpad[9]; 

... только оставляет пространство для 9. Это может перезаписывать стек (т.е. обратный адрес)

+0

Спасибо! Не заметил этого, я исправлю это немедленно. Но, к сожалению, программа работала хорошо, прежде чем я попытался использовать «struct» (а затем «union», чтобы увидеть, изменили ли это что-либо) для передачи значений из read_temp(); к main(); Я даже не знаю, правильно ли я это сделал, и если это лучший способ сделать это, нужно только узнать, как все работает! – zakkos

3

Это:

 temps.eratura = ~temps.eratura;     //2's complement 
     temps.eratura += 1;        
     temps.decimali = ~temps.decimali;    //2's complement 
     temps.decimali += 1; 

большой NOP, как temps - это union, а не struct. Что вы здесь делаете? Почему нет:

temps.eratura = -temps.eratura;

Возможно, вы имели в виду для второго члена union быть int? В этом случае он по-прежнему не работает, но имеет смысл в использовании в read_temp

И вы получаете доступ к 10 символам для массива 9 символов, как упомянуты другие.

Дополнительной информации на основе комментариев:

Вы определенно хотите использовать для ваших-структуры временных секретарей, как вы хотите 2 значения окрености в памяти. Кроме того, в то время как я не уверен, что ваш компилятор позволяет,

if(temps.eratura < 0){    
      temps.eratura = -temps.eratura; 
      temps.decimali = -temps.decimali; 
      lcd_send_dat('-'); 
    } 

Кажется немного для прямой вперед - позволяет компилятору обрабатывать 2s комплимент для вас.

следующие:

temp = (temps.eratura/100)& 0x0F; 

имеет очень мало места для работы в качестве значения может идти только до 128. В основном это установка темпа в 0, если temps.eratura меньше 100 и 1, если больше. Здесь нет необходимости в &. Ах, вы отправляете цифры. ОК.

temp = temps.eratura; 

if(temp >= 100) 
{ 
    temp -= 100; 
    lcd_send_dat('1'); 
} 

if(temps.eratura >= 10) 
{ 
    lcd_send_dat('0' + (temp/10)); 
} 

lcd_send_dat('0' + (temp % 10)); 

Тогда для десятичного:

const char decims[16] = 
    {'0', '0', '1', '1', '2', '3', '3', '4', '5', '5', '6', '6', '7', '8', '8', '9'}; 

и

lcd_send_dat('.'); 
lcd_send_dat(decims[temps.decimali]); 
lcd_send_dat(0xDF); 

или мы можем избавиться от преобразователя decims полностью с:

lcd_send_dat('0' + ((temps.decimali * 10)/16)); 

В принципе, все эти изменения позволяют компилировать r, чтобы сделать немного работы для вас и сделать код более удобным для подражания.

+0

Я попробовал «struct» перед использованием «union», но у меня такая же проблема. Код должен сделать дополнение 2-х членов обоих членов temps (1 дополнение плюс один), оба 8 бит в длину. Перед добавлением десятичных знаков (поэтому мне нужно передать 2 значения за пределами read_temp(), один для всей температуры и один для цифр после точки), он работал хорошо, значения, которые он получает от датчика, оцениваются правильно, тогда i добавлена ​​«структура», и все пошло не так ... – zakkos

+2

«Объединение» означает, что оба члена занимают одно и то же место в памяти. Я уверен, что это не то, что вы хотите. Поскольку изменение его от 'struct' до' union' все равно не помогло, я предлагаю изменить его обратно на 'struct' и исходя из этого. –

+0

Точно так же эти две строки не имеют смысла с вашим соединением, вы назначаете его и сразу же заменяете содержимое на следующей строке: temps.decimali = блокнот [0] & 0x0F; temps.eratura = (блокнот) [1] << 4) | (блокнот [0] >> 4); –

0

Это может быть компилятор C, оптимизирующий код, который может привести к появлению выполнения нелинейного кода ... Попробуйте выполнить один шаг с выключенным оптимизатором.

Смежные вопросы