View previous topic :: View next topic |
Author |
Message |
Danni
Joined: 05 Mar 2016 Posts: 10
|
the difference between PIC18f26k22 and PIC16f1847 |
Posted: Sat Mar 05, 2016 1:42 am |
|
|
Hello.
I am new in microcontroller and has a pickit 3 and a demo print with PIC18f26k22 I've tried different things.
Now I made a print with a PIC16f1847 and can not figure out what I need to do to get code that works on demo table to work on my own prints.
I have a DS18B20 + with parasitic power and a 4k7 pullup resistor. Have found the code in here that I use.
So I think it's something with the setup of my PIC.
Is there someone who can give my a hint.
Code: |
#include <16f1847.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES PUT //Power Up Timer
#FUSES NOMCLR
#FUSES NODEBUG
#use delay(clock=4000000)
#define DQ PIN_B3
//-------------------------------------
void ow_reset(void)
{
output_low(DQ);
delay_us(500); // Min. 480uS
output_float(DQ);
delay_us(500); // Wait for end of timeslot
}
//-------------------------------------
// Read bit on one wire bus
int8 read_bit(void)
{
output_low(DQ);
delay_us(1);
output_float(DQ);
delay_us(12); // Read within 15uS from start of time slot
return(input(DQ));
}
//-------------------------------------
int8 read_byte(void)
{
int8 i;
int8 val = 0;
for(i=0 ; i<8 ; i++)
{
if(read_bit()) val |= (0x01 << i);
delay_us(120); // To finish time slot
}
return val;
}
//-------------------------------------
void write_byte(int8 val, int8 power_on)
{
int i;
for(i=0; i<8; i++)
{
output_low(DQ);
delay_us( 2 );
output_bit(DQ, shift_right(&val,1,0));
delay_us(60);
if((i == 7) && (power_on == 1))
{
output_high(DQ);
}
else
{
output_float(DQ);
delay_us( 2 );
}
}
}
//==========================================
void main(void)
{
int8 i;
signed int16 temperature;
signed int8 scratch[9];
output_float(DQ);
while(1)
{
ow_reset();
write_byte(0xCC, 0); // Skip Rom command
write_byte(0x44, 1); // Temperature Convert command
delay_ms(750); // Max. time for conversion is 750mS
ow_reset();
write_byte(0xCC, 0); // Skip Rom command
write_byte(0xBE, 0); // Read scratch pad command
// Get the data bytes
for(i=0; i < 8; i++)
{
scratch[i] = read_byte();
}
ow_reset();
temperatur = scratch[1];
temperature = (signed int16) make16(scratch[1],scratch[0]);
if(temperature >= 0)
temperature = ((temperature + 8)/16)*10;
else
temperature = ((temperature - 8)/16)*10;
}
}
|
Regards Danni.. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Mar 05, 2016 3:47 am |
|
|
I haven't looked at the code. Just the fuses. Big problems.
'HS' says use an _external_ crystal running faster than 4MHz.
'INTRC_IO', then says to use the internal osclliator.
You can't have both. Use:
Code: |
#include <16f1847.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES PUT //Power Up Timer
#FUSES NOMCLR //MCLR pin disabled
#FUSES NODEBUG //'Run' mode.
#use delay(INTERNAL=4000000)
|
Your chip then has a chance of working.
Then always start _one step at a time_.
With these fuses use a simple program to just flash an LED on one pin. Verify this does flash, and flashes at the expected speed. You then know your chip is working, before trying to debug problems with your code.... |
|
|
Danni
Joined: 05 Mar 2016 Posts: 10
|
|
Posted: Sat Mar 05, 2016 5:37 am |
|
|
I think it's something with the setup but it has not solved the problem yet.
I have made two flashing diodes and they worked fine and 1 second seems to fit.
Also before i removed #fuses hs :-) |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sat Mar 05, 2016 6:44 am |
|
|
The 1Hz LED test is a 'rough' - OK I'm working test NOT very accurate.
You should use an oscilloscope and check the actual timings if possible. The internal RC clock may not be 4.000000000 MHz so your 1us won't be 1us.
These DS chips need precise timings.
So you may need to adjust the delays either more or less.
Whenever using 'time critical' code like timers, UARTs, DS chips it's best to use a real xtal/2caps.
Jay
also this..
temperatur = scratch[1];
looks like 'old code', needs to be deleted. |
|
|
Danni
Joined: 05 Mar 2016 Posts: 10
|
|
Posted: Sat Mar 05, 2016 8:01 am |
|
|
Yes sorry forgot to remove it.
The only thing i changed is i could not complie int8 scratch[9];
So changed it to Signed int8 scratch[9]; but isn't that the same or? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Mar 05, 2016 9:06 am |
|
|
No, they are not the same.
One has 8bits and accepts values from 0 to 255.The other has one bit reserved for the sign, and has values from -128 to +127.
What do you mean "i could not complie int8 scratch[9];". Why not?.
It'll change things when any maths, or logic operations are performed on the variable. |
|
|
Danni
Joined: 05 Mar 2016 Posts: 10
|
|
Posted: Sat Mar 05, 2016 1:21 pm |
|
|
when i use int8 scratch[9];
i get the error Unable to resolve identifier scratch
I read somewhere that signed int is the same as int :-S |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sat Mar 05, 2016 1:48 pm |
|
|
It sounds like you've made a few changes to your code so it would be best to post your current version.
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Mar 05, 2016 1:49 pm |
|
|
Quote: | when i use int8 scratch[9];
i get the error Unable to resolve identifier scratch |
That's an MPLAB X message. See this thread on the Microchip forum:
http://www.microchip.com/forums/m775535.aspx |
|
|
Danni
Joined: 05 Mar 2016 Posts: 10
|
|
Posted: Sat Mar 05, 2016 2:30 pm |
|
|
I use this now:
Code: |
#include <16f1847.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES PUT //Power Up Timer
#FUSES NOMCLR //MCLR pin disabled
#FUSES NODEBUG //'Run' mode.
#use delay(INTERNAL=4000000)
#define DQ PIN_B3
//-------------------------------------
void ow_reset(void)
{
output_low(DQ);
delay_us(500); // Min. 480uS
output_float(DQ);
delay_us(500); // Wait for end of timeslot
}
//-------------------------------------
// Read bit on one wire bus
int8 read_bit(void)
{
output_low(DQ);
delay_us(1);
output_float(DQ);
delay_us(12); // Read within 15uS from start of time slot
return(input(DQ));
}
//-------------------------------------
int8 read_byte(void)
{
int8 i;
int8 val = 0;
for(i=0 ; i<8 ; i++)
{
if(read_bit()) val |= (0x01 << i);
delay_us(120); // To finish time slot
}
return val;
}
//-------------------------------------
void write_byte(int8 val, int8 power_on)
{
int i;
for(i=0; i<8; i++)
{
output_low(DQ);
delay_us( 2 );
output_bit(DQ, shift_right(&val,1,0));
delay_us(60);
if((i == 7) && (power_on == 1))
{
output_high(DQ);
}
else
{
output_float(DQ);
delay_us( 2 );
}
}
}
//==========================================
void main(void)
{
int8 i;
signed int16 temperature;
int8 scratch[9];
output_float(DQ);
while(1)
{
ow_reset();
write_byte(0xCC, 0); // Skip Rom command
write_byte(0x44, 1); // Temperature Convert command
delay_ms(750); // Max. time for conversion is 750mS
ow_reset();
write_byte(0xCC, 0); // Skip Rom command
write_byte(0xBE, 0); // Read scratch pad command
// Get the data bytes
for(i=0; i < 8; i++)
{
scratch[i] = read_byte();
}
ow_reset();
temperature = (signed int16) make16(scratch[1],scratch[0]);
if(temperature >= 0)
temperature = ((temperature + 8)/16)*10;
else
temperature = ((temperature - 8)/16)*10;
}
}
|
with changed #fuses as Ttelmah told me to.
But the Unable to resolve identifier scratch is there but can download without any problem.
But still not working...[/code] |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sat Mar 05, 2016 2:43 pm |
|
|
OK... I don't see anything like a print statement to display the reading ??
Also if you have a spare I/O pin, add a resistor and LED and 'toggle' it in the 'forever loop' to confirm the program is running.
Jay |
|
|
Danni
Joined: 05 Mar 2016 Posts: 10
|
|
Posted: Sat Mar 05, 2016 2:54 pm |
|
|
I use a red/green led to blink the binary temperature out.
I used that on my demo board too, because its easy to see whats 1 and 0:
and a blink at the end.
Code: |
#include <16f1847.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES PUT //Power Up Timer
#FUSES NOMCLR //MCLR pin disabled
#FUSES NODEBUG //'Run' mode.
#use delay(INTERNAL=4000000)
#define DQ PIN_A7
#define LEDGRON PIN_A1
#define LEDROD PIN_A0
//-------------------------------------
void ow_reset(void)
{
output_low(DQ);
delay_us(500); // Min. 480uS
output_float(DQ);
delay_us(500); // Wait for end of timeslot
}
//-------------------------------------
// Read bit on one wire bus
int8 read_bit(void)
{
output_low(DQ);
delay_us(1);
output_float(DQ);
delay_us(12); // Read within 15uS from start of time slot
return(input(DQ));
}
//-------------------------------------
int8 read_byte(void)
{
int8 i;
int8 val = 0;
for(i=0 ; i<8 ; i++)
{
if(read_bit()) val |= (0x01 << i);
delay_us(120); // To finish time slot
}
return val;
}
//-------------------------------------
void write_byte(int8 val, int8 power_on)
{
int i;
for(i=0; i<8; i++)
{
output_low(DQ);
delay_us( 2 );
output_bit(DQ, shift_right(&val,1,0));
delay_us(60);
if((i == 7) && (power_on == 1))
{
output_high(DQ);
}
else
{
output_float(DQ);
delay_us( 2 );
}
}
}
void truebit()
{
output_high(LEDGRON); // 1 bit
delay_ms(81); //20 pc bruger kun en kort puls til at tælle low tid
output_low(LEDGRON);
delay_ms(41); //50
}
void falsebit()
{
output_high(LEDROD); // 0 bit
delay_ms(41); //20 pc bruger kun en kort puls til at tælle low tid
output_low(LEDROD);
delay_ms(81); //80
}
//==========================================
void main(void)
{
int8 i;
signed int16 temperature;
int8 scratch[9];
output_float(DQ);
while(1)
{
ow_reset();
write_byte(0xCC, 0); // Skip Rom command
write_byte(0x44, 1); // Temperature Convert command
delay_ms(750); // Max. time for conversion is 750mS
ow_reset();
write_byte(0xCC, 0); // Skip Rom command
write_byte(0xBE, 0); // Read scratch pad command
// Get the data bytes
for(i=0; i < 8; i++)
{
scratch[i] = read_byte();
}
ow_reset();
temperature = (signed int16) make16(scratch[1],scratch[0]);
if(temperature >= 0)
temperature = ((temperature + 8)/16)*10;
else
temperature = ((temperature - 8)/16)*10;
if((temperature & 0x0800) != 0x00)truebit();else falsebit();
if((temperature & 0x0400) != 0x00)truebit();else falsebit();
if((temperature & 0x0200) != 0x00)truebit();else falsebit();
if((temperature & 0x0100) != 0x00)truebit();else falsebit();
if((temperature & 0x0080) != 0x00)truebit();else falsebit();
if((temperature & 0x0040) != 0x00)truebit();else falsebit();
if((temperature & 0x0020) != 0x00)truebit();else falsebit();
if((temperature & 0x0010) != 0x00)truebit();else falsebit();
if((temperature & 0x0008) != 0x00)truebit();else falsebit();
if((temperature & 0x0004) != 0x00)truebit();else falsebit();
if((temperature & 0x0002) != 0x00)truebit();else falsebit();
if((temperature & 0x0001) != 0x00)truebit();else falsebit();
output_high(LEDROD);
output_high(LEDGRON);
delay_ms(1000); //20 pc bruger kun en kort puls til at tælle low tid
output_low(LEDROD);
output_low(LEDGRON);
}
}
|
|
|
|
Danni
Joined: 05 Mar 2016 Posts: 10
|
|
Posted: Sun Mar 06, 2016 1:33 pm |
|
|
But how does this work??
Code: |
int8 read_byte(void)
{
int8 i;
int8 val = 0;
for(i=0 ; i<8 ; i++)
{
if(read_bit()) val |= (0x01 << i);
delay_us(120); // To finish time slot
}
return val;
}
|
For me it looks like a counter that calls read_bit 8 times and puts a 0 or 1 in each of the int8 bits.
It looks like that it only reads read_bit one time in every scan. and it should read it 8 times?? or am i wrong?? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Mar 06, 2016 2:22 pm |
|
|
Quote: | It looks like that it only reads read_bit one time in every scan |
Make a test program to study the read_bit() routine.
The output of the test program is shown below. This output comes
from running the program in MPLAB vs. 8.92 simulator.
It shows that read_bit() is called 8 times by the read_byte() function:
Quote: |
read_bit() was called.
read_bit() was called.
read_bit() was called.
read_bit() was called.
read_bit() was called.
read_bit() was called.
read_bit() was called.
read_bit() was called.
Value read = 55 hex |
The test program is shown below. Instead of the normal read_bit()
function, a test function is substituted, which displays the
message "read_bit() was called". This allows us to see the number of
times it was called (Answer: 8 times).
Code: | #include <18F4620.h>
#fuses INTRC_IO,NOWDT,PUT,BROWNOUT,NOLVP
#use delay(clock=4M)
#use rs232(baud=9600, UART1, ERRORS)
int8 read_bit(void)
{
static int8 temp = 0;
printf("read_bit() was called. \r");
temp ^= 1; // Flip the return value to 0 or 1.
return(temp);
}
//-----------------------
int8 read_byte(void)
{
int8 i;
int8 val = 0;
for(i=0;i<8;i++)
{
if(read_bit()) val |= (0x01 << i);
delay_us(120); // To finish time slot
}
return val;
}
//========================
void main()
{
int8 value;
value = read_byte();
printf("Value read = %x hex \r", value);
while(TRUE);
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Sun Mar 06, 2016 2:50 pm |
|
|
To understand what's going on you really need to read the Dallas Semi datasheets on 'one-wire' operations. It will explain the 'how and why' of the one wire communications bus that they developed.
The short answer.. as PCM P points out, is that they 'create' a byte from 8 reads of the bus.
It is important to read their data sheets as timing is critical in using this bus unlike 'RS232' where it's all done 'behind the scene' in a UART.
Jay |
|
|
|