![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
CaptainOnedin
Joined: 27 Feb 2022 Posts: 7 Location: All over the world
|
Pic to pic UART data Transfer |
Posted: Sun Feb 27, 2022 1:38 pm |
|
|
Hi everyone,
I wanna make two pics communicate via UART. Those two pics are 16F628A and 12F675. So 16F628A has codes for displaying menu on i2c lcd. On the 12F675 is driving stepper motor with configurations should be sent by 16F628A. Now i can commence stepper motor run with uart communication. But at same time i wanna send more then one configuration and so i can adjust speed or running time of stepper motor. For example: I want to send A=1 and B=15. So 12F675 will run the code as if(A==1) Set_timer0(B);
Can someone help on this matter to solve sending 2 or more integers to other pic and make it understandable individually. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9168 Location: Greensville,Ontario
|
|
Posted: Sun Feb 27, 2022 7:22 pm |
|
|
1st problem you have is that the 675 doesn't have a HW UART, so you'll need to be careful in coding the SW UART. for sure I'd use 'timed rcv', check the CCS manual FAQ or Q&A section for 'timed receive' or 'timed button' ? You'll need to create a 'protocol' of say a start byte, Abyte, Bbyte, end byte. This then allows the receiving PIC to KNOW what is 'good data'.
For test/design purposes, I'd have the '628 (master) PIC send known data in a continuous loop with say a 2 second delay, then cut code for the 675(slave) PIC to receive and parse (decode) the data.
if you don't use the 'timed UART' code, it's very easy for the slave to get 'confused and hung'. |
|
![](templates/subSilver/images/spacer.gif) |
CaptainOnedin
Joined: 27 Feb 2022 Posts: 7 Location: All over the world
|
|
Posted: Sun Feb 27, 2022 8:03 pm |
|
|
Thanks for your kind reply @temtronic
Yes, 675 doesn't have hw uart. Therefore i am using interrupts on change option to catch Uart data. You can see 675 code as below.
Code: |
#include <12F675.h>
#use delay(clock=4MHz)
#fuses INTRC_IO,NOWDT,NOCPD,NOPROTECT,NOPUT,NOMCLR,NOBROWNOUT
#use rs232(baud=9600,rcv=pin_a5,stop=1,parity=N,bits=8,stream=pic)
const int adim[] = {0x01,0x03,0x02,0x06,0x04,0x14,0x10,0x11};
int i=0;
int thiz;
int A;
#int_timer0
void kesme(){
if(A==5) {set_timer0(248);
if(i>6) i=-1;
i++;
output_a(adim[i]);
}
if(A==4) {set_timer0(thiz);
if(i>6) i=-1;
i++;
output_a(adim[i]);
}
}
#int_ra
void degisimkesmesi(){
if(bit_test(input_change_a(),3)){
A=fgetc(pic);
}
}
void main()
{
setup_adc(adc_off);
setup_adc_ports(no_analogs);
enable_interrupts(global);
enable_interrupts(int_ra3);
clear_interrupt(int_ra);
setup_timer_0(T0_INTERNAL | T0_DIV_256);
set_tris_a(0x28);
output_a(0x00);
while(TRUE)
{
if(A==1){ disable_interrupts(int_timer0);
}
if(A==5){ enable_interrupts(int_timer0);
set_timer0(248);
}
if(A==4){ thiz=fgetc(pic);
}
}
}
|
I research "timed receive" and could not find any understandable things to me That's my hobby and i am at ocean atm. I'm seafarer. If it's possible to you can you show me small code example to i can understand more easy. Thanks alot. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Mon Feb 28, 2022 2:05 am |
|
|
Several things.
First, I have to say things would be enormously easier if you just used a
chip that had a hardware UART. There are plenty now.
Second use a chip that supports a higher clock rate. At 4MHz, things
take a lot of time, and this may cause issues....
Now that having been said, the first issue is with your handling of the IOC,
and the serial. Several things:
The serial is on A5. Why then are you enabling the interrupt on A3?.
You don't need to test input_change. Since the interrupt is enabled on
one pin only, the interrupt implies this pin has changed.
After you have read the byte, read A5 once. This ensures the change
flag is cleared on leaving the interrupt. So:
Code: |
#int_ra
void degisimkesmesi(void)
{
int dummy;
A=fgetc(pic);
A=input(PN_A5); //ensure IOC flag is clearable
}
|
Change the interrupt enable to:
Code: |
enable_interrupts(global);
while (input(PIN_A5==0)
; //wait till serial line is high - this also clear the flag bit.
clear_interrupt(int_ra); //ensure interrupt is cleared before enabling
//If this was set, you cannot clear it until the port is read. Reading
//the pin above, allows this to be cleared.
enable_interrupts(int_ra5);
|
Then the next problem. You have a timer interrupt that can occur
quite often (at 248, just every 512 instructions). If the code is in this
handler when the interrupt triggers, there could be several dozen
instructions delay before the code gets into the RA interrupt handler.
This then means you could be sampling quite late in the bit.
So change your #USE RS232 to:
#use rs232(baud=9600,rcv=pin_a5,stop=1,parity=N,bits=8,SAMPLE_EARLY,
stream=pic)
This makes the fgetc start sampling immediately when it is called. Given
that getting into the interrupt will take at least 35uSec, and if the code
is in the timer interrupt could be up to perhaps 200uSec, this is better.
Understand IOC. The flag for this is set, whenever the actual pin value
does not match the last 'read' level. Hence you cannot actually clear this
(it just gets set again), until you read the port pin involved.
Now on your two integer problem, are you sure you need two values?.
Remember an integer is 8 bits. If your numbers are only 0 to 15 each,
you could send both as a single byte. So the binary number becomes:
AAAABBBB
This is easy to work with and encode/decode. Worth thinking about?.
Otherwise you need to count. To ensure the counters are synchronised,
use some otherwise not used value (possibly 0?), to say to the slave
counter=0, then send the bytes one after the other, and have your
interrupt put the first byte into A, and the second into B. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9168 Location: Greensville,Ontario
|
|
Posted: Mon Feb 28, 2022 6:16 am |
|
|
I agree 100% with Mr. T about the choice of PIC.
You already have a '628, perhaps use another to replace the '675 ??
The problem with smaller PICs is never enough pins, not fast enough, not enough memory, lack of peripherals and possible code problems.
You should look to see what Microchip offers to upgrade from the '628, in the same package you're using now. Be sure it'll work with your compiler version and programmer. Often you can get a more powerful PIC for less money !
By using ONE version of PIC, you get to create your own library of functions and drivers, that you know work. LCD, KPD, RTC, etc. so you can reuse them in future projects. |
|
![](templates/subSilver/images/spacer.gif) |
CaptainOnedin
Joined: 27 Feb 2022 Posts: 7 Location: All over the world
|
|
Posted: Mon Feb 28, 2022 10:17 am |
|
|
Thanks for yr reply @Ttelmah
As i told before msg i am at middle of the atlantic ocean atm. 😄 I have got only 2 pcs 628A and 1 pcs 675. For sure i wll try to use 2 628A to Uart communication with 20mhz crystal as you mentioned as useful.
As you know there isn't uart interruption on 675. So i had tried many times to catch data correctly with IOC on a5. But it have not effect any yet. Then i thought i can get data with additional Ioc on a3. And it works. So i simply apply the first rule of coders"if it works, don't touch it."😄 Also tried your adviced code, it did not work.
I didn't know Sample_early options and its benefits. So thanks for it i will use it accordingly.
Yeah you are right, i will only send a byte including number fm 0-15. For all that new issue will arise for me 😄 How can pic divide a byte and decode it? For example; Aaaabbbb is my byte. AAAA will submit only which menu i am in. And BBBB will submit options as we make on lcd interface. May be its simple way to learn requesting code examples but i can understand easily on this way. Thanks alot. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19358
|
|
Posted: Mon Feb 28, 2022 10:42 am |
|
|
If the RA doesn't work on A5, it almost certainly means something else
is wrong with this pin. You need to triple check the signal genuinely is
getting to the pin. I'd change your clock setup, to INTERNAL=4MHZ, which
ensures the internal oscillator is selected. Put the clock line after the
fuses.
The signal levels on RA5 are identical to RA3. It should work.
Do a very simple test and read RA5, and copy the level to another
pin. I'd suspect you have something physically wrong, either with the
connection or the PIC itself.
If you have to use RA3, then put the UART on this pin. |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9168 Location: Greensville,Ontario
|
|
Posted: Mon Feb 28, 2022 3:16 pm |
|
|
to decode or 'parse' the byte into the two nibbles....
highnibl= variable & 0b11110000; // 240, top 4 bits
lownibl=variable & 0b00001111; // 15, bottom 4 bits
Pretty sure that'll work, best to check though !
It's one of those 'simple' things that my mind complicates, then I get confused ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
CaptainOnedin
Joined: 27 Feb 2022 Posts: 7 Location: All over the world
|
|
Posted: Mon Feb 28, 2022 3:45 pm |
|
|
@Ttelmah thanks for yr prompt reply.
Here is my latest code for slave pic 675 according to yr advice.
Code: | #include <12F675.h>
#fuses INTRC_IO,NOWDT,NOCPD,NOPROTECT,NOPUT,NOMCLR,NOBROWNOUT
#use delay(internal=4MHz)
#use rs232(baud=9600,rcv=pin_a3,stop=1,parity=N,bits=8,SAMPLE_EARLY,stream=pic)
const int adim[] = {0x03,0x06,0x14,0x11};
int i=0;
int16 kesmetekrar;
int A;
#int_timer0
void kesme(){
set_timer0(248);
if(i>3) i=-1;
i++;
output_a(adim[i]);
}
#int_timer1
void timerkesme(){
set_timer1(60536);
if(i>3) i=-1;
i++;
output_a(adim[i]);
kesmetekrar++;
if(kesmetekrar==300){
kesmetekrar=0;
disable_interrupts(int_timer1);
output_low(pin_a0);
output_low(pin_a1);
output_low(pin_a2);
output_low(pin_a4);}
}
#int_ra
void degisimkesmesi(void){
if(bit_test(input_change_a(),3)){
A=fgetc(pic);
if(A==1){ disable_interrupts(int_timer0);
output_low(pin_a0);
output_low(pin_a1);
output_low(pin_a2);
output_low(pin_a4);
A=0;
}
if(A==5){ enable_interrupts(int_timer0);
set_timer0(248);
a=0;
}
if(A==4){ enable_interrupts(int_timer1);
set_timer1(63536);
a=0;
}
}
}
void main()
{
setup_adc(adc_off);
setup_adc_ports(no_analogs);
enable_interrupts(global);
while(input(pin_a3==0));
disable_interrupts(int_timer0);
disable_interrupts(int_timer1);
clear_interrupt(int_ra);
enable_interrupts(int_ra3);
setup_timer_0(T0_INTERNAL | T0_DIV_256);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
set_tris_a(0x28);
output_a(0x00);
while(TRUE)
{
}
}
|
It still does not interrupt the code and catch the data. Here is my proteus diagram same as real one.
[img]https://ibb.co/QjCYJJR[/img]
On the other hand if i cannot achieve that ICO, i have to continue with my working way and need help for decode the byte as mentioned before. Could you help? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 28, 2022 4:45 pm |
|
|
In your latest post, your code is using pin A3 (MCLR) for the Rx input,
but your schematic shows pin A5 is used. They need to be the same.
I personally never use MCLR for anything but MCLR. I put a 10K
pullup on it and leave it alone. Just for safety's sake. |
|
![](templates/subSilver/images/spacer.gif) |
CaptainOnedin
Joined: 27 Feb 2022 Posts: 7 Location: All over the world
|
|
Posted: Mon Feb 28, 2022 5:22 pm |
|
|
@PCM programmer yes i draw wrong on Proteus. We can imagine it as connected to a3. Nevertheless normally i am using A5 for rx but after @Ttelmah msg i made that connections for trial. |
|
![](templates/subSilver/images/spacer.gif) |
jeremiah
Joined: 20 Jul 2010 Posts: 1328
|
|
Posted: Mon Feb 28, 2022 6:11 pm |
|
|
CaptainOnedin wrote: | And it works. So i simply apply the first rule of coders"if it works, don't touch it."😄 A |
The others have given you good advice on the main part, but I wanted to touch on this. When we get new coders in, we often hear this meme, but I definitely want to impress on you:
If something seems to work one way and not the other and you don't understand why, then that is a serious issue and it often times will bite you at the worst point (after delivery to a customer for example).
We don't let any engineer, SW or otherwise, get away with just leaving something "that works" without us figuring out the why and then determining if we should keep the current solution or improve it based on that knowledge.
You are your own person, but I want to suggest you reconsider the position and figure out why A5 doesn't work and A3 magically does. Magic is never the answer! |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9168 Location: Greensville,Ontario
|
|
Posted: Mon Feb 28, 2022 6:43 pm |
|
|
Did a very, very quick read of the datasheet...
section 3.2, additional pin functions.. pullups....
NO internal PULLUP on GP3
This 'might' be the problem if YOU didn't put a real resistor on GP3.
Jay |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Feb 28, 2022 7:40 pm |
|
|
I have another comment on the Pin A5 thing.
In your 2nd post in this topic, you posted your code.
I will post fragments of it below.
Here you specify Pin A5 for Rx:
Quote: | #include <12F675.h>
#use delay(clock=4MHz)
#fuses INTRC_IO,NOWDT,NOCPD,NOPROTECT,NOPUT,NOMCLR,NOBROWNOUT
#use rs232(baud=9600,rcv=pin_a5,stop=1,parity=N,bits=8,stream=pic)
|
Here you are testing bit 3 for some reason, but your data is coming
in on Pin A5. So your test is wrong. Nothing's happening on pin A3.
You don't need to test it. It's self defeating.
Quote: | #int_ra
void degisimkesmesi(){
if(bit_test(input_change_a(),3)){
A=fgetc(pic);
}
} |
Here in main(), you're enabling interrupts on Pin A3, but your
#use rs232() has Pin A5 setup as the receive pin.
Quote: | void main()
{
setup_adc(adc_off);
setup_adc_ports(no_analogs);
enable_interrupts(global);
enable_interrupts(int_ra3);
clear_interrupt(int_ra);
setup_timer_0(T0_INTERNAL | T0_DIV_256);
|
It's my belief that these tons of mistakes that you're making are
probably the reason why Pin A5 never worked. |
|
![](templates/subSilver/images/spacer.gif) |
CaptainOnedin
Joined: 27 Feb 2022 Posts: 7 Location: All over the world
|
|
Posted: Mon Feb 28, 2022 10:05 pm |
|
|
@jeremiah Thanks alot for your advice, i'll consider it all the time. But as you can get it i am trying to figure out how can i use A5 and the other questions. I wrote that keeping as it works due to lack of time onboard ship.
@temtronic yup i know that but while iam using IOC on A3 it works well. Only with RX mode it doesn't. And while using A5 inteeruot and rx with same codes there is nothing also.
@PCM programmer mate,i have changed the code after advices. Before i was using additional interrupt to catch data on A5. It was something like that on master pic(628A)
Code: | output_high(pin_b3);
delay_ms(100);
Output_low(pin_b3);
fputc(speed,pic);
|
That code triggers the A3 pin on 675 and than after A5 commences rx mode and catches data. Thas why firstly my code was like you mentioned.
For know, i am trying to figure out why interrupts are triggered when uart data comes on A5 or A3. And also how can i send two 4 bit data in a byte and divide/parse after receiving on other pic.
Thans for your replies guys. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|