View previous topic :: View next topic |
Author |
Message |
ralph79
Joined: 29 Aug 2007 Posts: 87
|
18f26k40 |
Posted: Sun Oct 14, 2018 2:07 am |
|
|
hello to all,
I'm using the PIC18F26k40 in a brand new project with the CCS V5.078 and this micro (or the compiler) is giving me headaches.
I have problems in some pins that are inputs (with the function set_tris_x), and it is not hardware. I have double checked around 100 times, also have problems with the pwm, timers, etc.. so my question is there any better include file for this micro or workarounds.. or this micro is really a mess?? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Sun Oct 14, 2018 3:00 am |
|
|
'As a separate 'general comment', you do realise that even if you have set the TRIS, if the chip is in standard I/O mode, this will be overridden if you do other I/O on the port?. So:
Code: |
set_tris_a(0xF); //here A0 to A3 are inputs
output_a(0); //Now all pins on A are outputs....
|
I've used your chips 'big brother' the 27K40, and there are some oddities (the ones already pointed out by PCM Programmer', and a couple of errata (Timer 0 must be set to ASYNC, when using Fosc/4, AD clock internal has a timing issue, and there are some debug oddities primarily)). However every pin on the chip has ended up doing what I tell it OK....
Remember if you want to do external counting or something similar with a timer, or use a PWM, that almost all the peripherals on this chip are PPS devices, so #PIN SELECT will need to have been used. Also remember to turn the comparator off before using any of the pins this uses. |
|
|
ralph79
Joined: 29 Aug 2007 Posts: 87
|
|
Posted: Mon Oct 15, 2018 3:36 am |
|
|
Thanks for the feedbacks PCM and Ttelmah,
PCM - about the PWM you are 100% correct about the PWM is necessary to put the T2_CLK_INTERNAL in all timers ( I didn't tested in the TIMER0, I'm using WDT);
For the TRIS function, the problem isn't in the TRIS function but in the output_high/output_low/input.
Ttelmah - I had to change the input(PIN_B0) do the following: (input_c() && 0b00100000) == 0b00100000
the same is necessary to do in the output functions: is necessary to do something similar. At this moment I'm making further tests... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Oct 15, 2018 3:48 am |
|
|
Er. You do realise what you show is testing C5, not B0?....
Is it possible you have something wrong in your actual pin numbers being used?. |
|
|
ralph79
Joined: 29 Aug 2007 Posts: 87
|
|
Posted: Mon Oct 15, 2018 4:24 am |
|
|
sorry Ttelmah I have mismatch the typing, the code is the following:
((input_b() && 0b00000001) == 0b00000001) for the PIN_B0
(input_c() && 0b00100000) == 0b00100000 for the PIN_C5
With this I have solved the problem of the input(PIN_B0) and of the input(PIN_C5)..
So now, the problem I have at this moment is when I make the following:
output_high(PIN_B4),some pins of the portB are "1" when the only one that should be "1" was the PIN_B4. It seems that output function put other pins than the one it should... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Oct 15, 2018 4:36 am |
|
|
OK. Have just tested, for your chip, with your compiler version, and the input(PIN_B0); instruction is accessing the right bit in the chip.
Similarly output_high(PIN_B4); correctly accesses the right bit.
There is one 'output' issue I realise that applies to the chips. They have slew rate limits enabled on the outputs by default. You need to turn these off for most applications. This has been mentioned here a couple of times.
Seriously real 'oddities' like this are most commonly actually an issue like an inadequate supply or an actual faulty chip. You have got _both_ Vss connections made?. Missing one can lead to real odd behaviour. |
|
|
ralph79
Joined: 29 Aug 2007 Posts: 87
|
|
Posted: Mon Oct 15, 2018 8:35 am |
|
|
ok.. problem solved/fixed...
the solution...it is not necessary to:
- change the slew rate, although I had implemented in my code..
- use the code (input_b() && 0b00000001) == 0b00000001). The input(PIN_B0) works OK.
the real reason is that I use the ADC, and somehow is necessary to put the ANSELB after the setup_adc_ports function.
So the code must be something like:
Code: | setup_adc_ports(NO_ANALOGS);
setup_spi(SPI_SS_DISABLED);
setup_comparator(NC_NC_NC_NC);
setup_adc_ports(sAN8 | sAN10 | sAN13 | VSS_VDD); // set adc input, voltage reference
ANSELB &= 0b00100110; // if i don't put this line all the inputs are analog...or are not digital :P |
thanks for all Ttelmah and PCM |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 15, 2018 8:49 am |
|
|
ralph79 wrote: |
use the code (input_b() && 0b00000001) == 0b00000001). The input(PIN_B0) works OK.
|
Can you post the actual line of code in program that is doing the above ?
Because if I try to compile that line (but with a semi-colon at the end
instead of a period), I get a compilation error. I'm curious what your
actual line is. And in truth, I remain skeptical that it's necessary. |
|
|
ralph79
Joined: 29 Aug 2007 Posts: 87
|
|
Posted: Mon Oct 15, 2018 11:27 am |
|
|
indeed the line is the following:
Code: |
if((input_b() && 0b00000001) == 0b00000001)
{
// TODO
}
|
As I said the above code it is not necessary, neither the slew rate (which I began to use)... the only code that is need (because I use adc reads) is the following:
Code: |
#include <18F26K40.h>
#device *=16
#device ADC=10
#FUSES WDT //Watch Dog Timer
#FUSES WDT1024 //Watch Dog Timer uses 1:1024 Postscale
#FUSES NOEXTOSC //External Oscillator not enabled
#FUSES RSTOSC_HFINTRC_64MHZ
#FUSES NOCLKOUT //I/O function on OSC2
#FUSES NOCKS //Clock Switching Disabled
#FUSES NOFCMEN //Fail-safe clock monitor disabled
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES PUT //Power Up Timer
#FUSES PROTECT //Code not protected from reading
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NOSTVREN //Stack full/underflow will cause reset
#FUSES BROWNOUT
#FUSES BORV27 //Brownout reset at 2.5V
#use delay(internal=64MHz,restart_wdt)
#PIN_SELECT U1TX = PIN_C6
#PIN_SELECT U1RX = PIN_C7
#PIN_SELECT U2TX = PIN_B6
#PIN_SELECT U2RX = PIN_B7
#pin_select CCP1OUT=PIN_C2
#pin_select CCP2OUT=PIN_C1
#byte ANSELB=getenv("SFR:ANSELB")
#byte SLRCONA=getenv("SFR:SLRCONA")
#byte SLRCONB=getenv("SFR:SLRCONB")
#byte SLRCONC=getenv("SFR:SLRCONC")
#use rs232(baud = 9600,parity=N, xmit = PIN_C6, rcv = PIN_C7, bits=8, stream=PORT1, errors, restart_wdt)
#use rs232(baud= 19200,parity=N, xmit = PIN_B6, rcv = PIN_B7, bits=8, stream=PORT2, errors, restart_wdt)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(E)
#priority int_RDA2, INT_RDA
void main(void)
{
setup_oscillator(OSC_HFINTRC_64MHZ);
set_tris_a(0b10101000); // set data I/O directions
set_tris_b(0b01101111); // set data I/O directions
set_tris_c(0b10111001); // set data I/O directions
set_tris_e(0xFF); // set data I/O directions
//////
//---- the rest of code
////
SLRCONA = 0;
SLRCONB = 0;
SLRCONC = 0;
setup_adc_ports(sAN8 | sAN10 | sAN13 | VSS_VDD); // set adc input, voltage reference
ANSELB &= 0b00100110; // if i don't put this line all the inputs are analog...or are not digital
output_low(PIN_B4);
//////
//---- the rest of code
////
while (1)
{
// todo
///
if (!input(PIN_B0))
{
// the remain code
}
else
{
//
}
}
} |
if I don't put the ANSELB portion of code..the "if (!input(PIN_B0))" line has unwanted results..
P.S. Note the code was edit in this post.. it was not compiled.. I hope I didn't forget any ";" or ")" |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon Oct 15, 2018 12:29 pm |
|
|
One other thing is wrong:
setup_spi(SPI_SS_DISABLED);
This _enables_ the SPI port. Not what you want I think. The syntax to disable the SPI is:
setup_spi(FALSE); |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Mon Oct 15, 2018 12:32 pm |
|
|
just 2 comments.
1) this...
set_tris_c(0b10111001); // set data I/O directions
set_tris_e(0xFF); // set data I/O directions
you should be code them the same..
ie: set_tris_e(0b11111111); // set all for inputs.
mixing binary and hex is kinda 'messy'.
2) get rid of the WDT code. Until your code is 100% working, do NOT enable the WDT feature. It's NOT necessary and can cause weird 'problems' to crop up !!
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Oct 15, 2018 12:59 pm |
|
|
ralph79 wrote: |
setup_adc_ports(sAN8 | sAN10 | sAN13 | VSS_VDD); // set adc input, voltage reference
ANSELB &= 0b00100110; // if i don't put this line all the inputs are analog...or are not digital
if I don't put the ANSELB portion of code..the "if (!input(PIN_B0))" line has unwanted results..
|
In your setup_adc_ports() line above, you are telling the compiler that
you want sAN8 to be an analog pin. Also, you're ANDing ANSELB with 0x26.
If we look at the .LST file, we see the compiler setting ANSELB to 0x25.
Quote: |
.................... setup_adc_ports(sAN8 | sAN10 | sAN13, VSS_VDD);
000AC: MOVLW 00
000AE: MOVWF x58
000B0: MOVWF x11
000B2: MOVLW 25
000B4: MOVWF x19 // ANSELB register
000B6: MOVLW 00
000B8: MOVWF x21
|
0x25 is 0010 0101 in binary. The bottom bit is for sAN8. It's set to a '1',
which means it's set as an analog pin.
But then, you don't like this, so you And ANSELB with 0x26 to clear ANSB0.
Conclusion:
You have an error in your coding. You really want sAN9 to be analog:
Quote: | setup_adc_ports(sAN9 | sAN10 | sAN13, VSS_VDD);
|
Look at the .LST file that we get now. It's what you want. Now you no
longer need the separate line dealing with ANSELB.
Quote: |
000AC: MOVLW 00
000AE: MOVWF x58
000B0: MOVWF x11
000B2: MOVLW 26
000B4: MOVWF x19 // ANSELB register
000B6: MOVLW 00
000B8: MOVWF x21
|
Also note in the setup_adc_ports line I posted, that VSS_VDD is separated
from the first group with a comma. This is the method shown in the .h
file for the PIC:
Quote: | void setup_adc_ports(int32 pins, int32 reference);
|
VSS_VDD is the voltage reference parameter.
In addition to that, this is probably not what you really wanted to write:
Quote: | if((input_b() && 0b00000001) == 0b00000001)
{
// TODO
} |
You are using the '&&' operator, which is a logical operator. It will cause
the result of input_b() to be converted to 0 or 1, and the expression will
be evaluated as a True/False expression. That's not what you really wanted.
I'm sure that you wanted it to be a test if bit B0 was 0 or 1. You should
have used the bitwise operator '&'. |
|
|
ralph79
Joined: 29 Aug 2007 Posts: 87
|
|
Posted: Tue Oct 16, 2018 11:49 am |
|
|
In fact there was an error with the pins, another colleague has given me the analog entrys (incorrectly!!!!), so as you said if I put it correctly:
Code: | setup_adc_ports(sAN9| sAN10| sAN13[b],[/b] VSS_VDD); // set adc input, voltage reference |
it is works correctly...really so sorry for this mistake, I should read a little better the include file for micro...
about the other portion:
Code: | if((input_b() && 0b00000001) == 0b00000001) |
In fact I also add make a mistake in my code... so dumb. I had think correctly and I had wrote badly. In this case the result will be same, but in the other case would be incorrect...sorry... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Wed Oct 17, 2018 12:43 am |
|
|
As you probably saw, we were beginning to suspect that you had a hardware issue....
At least it really is a simple one!.. |
|
|
|