|
|
View previous topic :: View next topic |
Author |
Message |
arelone
Joined: 06 Dec 2015 Posts: 42
|
Receive and Transmit string using UART |
Posted: Mon Feb 01, 2016 10:42 am |
|
|
Hi,
I would like to execute a program to read adc value from 9 channels. Upon completion of the conversion for 9 channels, a character 'E' is send for acknowledgement that the data has ended. The flow chart is shown in the attached file. I am using dspic30F6014a with 20MHz oscillator. I made a program and would like to know if you guys can have a look at the program. I compiled the code and without any errors but with a warning. However for the time being I could not test the code with UART since I have problem with the communication port (yet still trying to solve the problem). Honestly I am a beginner and not an expert. Hope. Any good advice from the expert members are very much appreciated.
http://s23.postimg.org/a7q22tgpn/UART_2.jpg
Code: |
#include <Send NAN string.h>
#use rs232(baud=9600,UART1)
void main()
{
char char_in;
setup_adc_ports(sAN0, VSS_VDD);
setup_adc(ADC_CLOCK_DIV_64 | ADC_TAD_MUL_8);
const int8 channel1[]=4,5,6,7,8,9,10,11,12;
int16 ADC_value[sizeof(channel1)];
int8 value;
int z;
SETUP_ADC_PORTS(0xFFFFFFFF); //all analogue
//while(TRUE)
for (z=1;z=16;z++) //loop for 16 times
{
char_in=getc(); //get character from UART
while(char_in==0x53) //wait till hex value 0x53 is received to start acquisition if not send n character
putc('n');
for (value=0;value<sizeof(channel1);value++) // read from 9 adc channels
{
set_adc_channel(channel1[value]);
ADC_value[value]=read_adc(); //ADC readings
printf("%04lu\n", ADC_value[value]);
}
putc(0x45); //send character 'E' for end of data
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Mon Feb 01, 2016 11:07 am |
|
|
Post the contents of the include file showing your fuses etc..
Without this we can't see if the configuration is even close to right.
How have you got the serial connected?. Max232?. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Mon Feb 01, 2016 9:57 pm |
|
|
Hi Ttelmah,
Thanks for the reply. Currently I am using UART1 from the dsPIC30F and connected to the USB port (COM4) using USB to UART converter. I just loaded the program code and try to observe the output using hyper terminal software. Unfortunately I did not receive the character 'n' when the input is NOT equal to 0x53 . What mistakes did I make here? Please advice.
Below is the .h file
Code: | #include <30F6014A.h>
#device ADC=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT //No brownout reset
#device ICSP=1
#use delay(crystal=20000000) |
|
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Mon Feb 01, 2016 10:04 pm |
|
|
Hi,
These are the port settings at COM4. The settings are the default settings excluding the baud rate.
baud rate=9600; data bits=8, parity=none; flow control=hardware
Thanks |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Tue Feb 02, 2016 1:56 am |
|
|
One glaring line:
for (z=1;z=16;z++)
This sets z to 1, then sets z to 16.....
This will give a 'non zero' (FALSE) return, so the loop will never execute.
'=' in C is the 'assignment' operator. '==' is the logical test. However you need z<=16
Which will return 'TRUE' if z is less than or equal to 16.
After the 16th character is received, the code will currently die. Is this what you want?.
Then when you do receive 'S', the code will not start acquiring, it'll sit forever sending 'n'....
You want something like:
Code: |
for (z=1;z<=16;z++) //loop for 16 times
{
while (TRUE)
{
char_in=getc(); //get character from UART
if (char_in=='S')
break; //exit loop if 'S'
else
putc('n'); //not 'S'
} //wait till 'S' is received to start
//acquisition if not send 'n' reply
//get here when 'S' is seen
for (value=0;value<sizeof(channel1);value++)
// read from 9 adc channels
{
set_adc_channel(channel1[value]);
ADC_value[value]=read_adc(); //ADC readings
printf("%04lu\n", ADC_value[value]);
}
putc(0x45); //send character 'E' for end of data
}
|
Then there is the big question of how this USB to UART you have works?. Most standard ones are (semi) RS232 output (usually lower voltage than traditional RS232, but still using RS232 signalling standards), so you need a MAX232 or equivalent between the PIC and the unit. There are a few more specialist units that are TTL output, that can be connected directly.
If your unit is a normal USB to serial adapter, you need an interface chip.... |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Wed Feb 03, 2016 9:14 am |
|
|
Hi Ttelmah,
Thanks for the explanation, I really appreciate your kindness. For the USB to UART converter (UC00A) I am using the third party converter from Cytron Tech. It is cheap and easy to use.
However I found some other problems. I loaded the code using USB ICSP PIC programmer (UIC00B) from Cytron Tech. and tried to observe the output but it seems that nothing comes out from the PIC. It is similar that the code was never loaded to the device. I am using pic kit2 and the software is able to detect the device and perform erase, read and write operations. I found out probably the problem comes from the .h file and it is related to the device configurations. Previously in MPLAB the dspic30F device configuration settings is as follows:
Code: | _FWDT(WDT_OFF);
_FOSC(CSW_FSCM_OFF & HS);
_FBORPOR(PBOR_OFF & PWRT_64 & MCLR_DIS);
_FGS(CODE_PROT_ON);
|
The problem is how to configure the above settings in CCS ? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Feb 03, 2016 9:34 am |
|
|
In the same order:
#fuses NO_WDT
#fuses CKSNOFSM. HS
#fuses NOBROWNOUT, PUT64, NOMCLR
You don't want 'code protection on' for development. This forces a full chip erase to be done every time you program, so uses up 'lives' on the flash memory more than really needs to happen. The programmer will normally only program things that have actually changed.
Once you have the code fully working, add:
#fuses PROTECT
to enable the protection. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Wed Feb 03, 2016 10:01 am |
|
|
Hi
Thanks Mr Ttelmah for the quick reply. But the problem remains. Have you faced the same problem before? Any advice to solve the problem?
Code: |
#fuses NOWDT
#fuses CKSNOFSM, HS
#fuses NOBROWNOUT, PUT64, NOMCLR |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Feb 03, 2016 11:23 am |
|
|
The thing to do, is take one step at a time.
Do the standard 'flash an LED' test.
Get this working, and flashing at the right rate.
Once this is done, you know that the PIC is running, and running at he right speed.
Then step on an try the RS232 (hurrah you have a connection that ought to work).
Then move on to beginning the actual code.
Typical silly things would be a little whisker stopping a pin working. Wrong capacitors on the crystal. Faulty crystal (does happen). etc etc.. |
|
|
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Wed Feb 03, 2016 4:36 pm |
|
|
One thing I always do if my project either has a display or uart for sending stuff is at startup, print a message about "project x, version y.z" or something - gives you a chance to see that the program is alive. If you don't get there, the rest of it isn't going to work either.
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Wed Feb 03, 2016 6:20 pm |
|
|
It's my standard practice to include 2 dedicated debug LEDs on all my commercial products. With those, I can troubleshoot anything.
Edit: Had a request that I elaborate.
Most of my products lack any sort of "friendly" human interaction device like a debug serial port or LCD. That greatly limits your debugging options to pretty much just flashing an LED.
I start by creating a PCB, then I switch to writing the firmware for that board. When I get prototype boards, it's then time to debug the firmware.
First test? Flash an LED for 1000ms on, 1000ms off. This confirms that your oscillator is running and running at the correct rate.
Next test? Basically "divide and conquer". Choose the simplest function that your board performs, comment out all other code, and try to verify that it works. If your board communicates with some other piece of equipment that can log into or otherwise hack, then debugging gets a lot easier. If not, you're stuck with your two debug LEDs. First I put in simple tests to see if the end result of whatever function passes a sanity check. Is the result within an expected range => turn on LED 1. If not, turn on LED 2.
Darn, LED 1 isn't on....why? Back up, start verifying the steps you took to end up at the result. Start putting LED on/off statements to see where your code is branching and whether the math is making sense. Your mistake soon becomes painfully obvious.
The 2nd LED is especially useful to show you where code is branching. Once you see what parts of your code is executing in response to certain stimuli, you can figure out where you went wrong or, more rarely, where the compiler is going wrong.
Next tackle some other function using the same approach. Repeat until you have uncommented all your code. In no time you'll have a fully functioning product. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Thu Feb 04, 2016 8:27 pm |
|
|
Hi,
I make a new project for simple ON/OFF LED with delay 1000ms. I erased the device and load the program and it works. However when I loaded the program for the 2nd time then it was not working. I make another new project with the same code loaded and it works again. Same as before it was not working when I loaded the program for the 2nd time. I really had no idea what is happening here. Please help. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Sun Feb 07, 2016 9:08 am |
|
|
Hi,
I confirmed that there is problem with my dspic30f. For the time being, I decided (for temporarily) using the 18F4580 device.
I am trying to observe the adc values from the pic using LabVIEW platform. I make some modifications from the earlier code in this discussion. The new code is as following:
Code: |
#include <18F4580.h>
#device ADC=8
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
void main()
{
unsigned char char_in;
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_DIV_64 | ADC_TAD_MUL_8);
const int8 channel1[]=0,1,2,3,4,5,6,7;
int16 ADC_value[sizeof(channel1)];
int8 value;
int z;
SETUP_ADC_PORTS(ALL_ANALOG); //all analogue
output_low(PIN_B6);
output_low(PIN_B7);
for (z=0;z<8;z++) //loop for 8 times
{
while (TRUE)
{
//wait till 'S' is received to start acquisition if not send 'n' reply
char_in=getc(); //get character from UART
if (char_in=='S')
break; //exit loop if 'S'
else
putc('n'); //not 'S'
output_high(PIN_B6);
}
//get here when 'S' is pressed
output_low(PIN_B6);
output_high(PIN_B7);
for (value=0;value<sizeof(channel1);value++)
// read from 9 adc channels
{
set_adc_channel(channel1[value]);
delay_us(10);
ADC_value[value]=read_adc(); //ADC readings
printf("%04lu\n", ADC_value[value]); //4 digit adc value and new line between value
}
}
}
|
The program should read from adc ch0-ch7 for 8 times (0,1...7). However when the code entering the second loop (z=1) the LabVIEW gives an error. I checked the flow and found out at the beginning of the second loop (z=1) the error starts. Somehow the code could not execute for the second loop. Any ideas why this occurs? Please advice. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Sun Feb 07, 2016 12:03 pm |
|
|
Several little things:
Get in the habit of using the C variable declaration locations. In C itself, variables have to be declared at the start of a code section (so the beginning of a function, or a loop. Now, 'mid block' declaration is accepted in things like C++, and CCS accepts it, _but_ it can result in slightly unexpected results, so better to keep to the original C standard.
Then, standardise on your variable usage. You are using int, int8, char etc.. If you are using int8, which ensures the correct size, then don't use 'int', which will be a different size when you use the larger PIC.
Then only setup the adc ports once.
You don't actually need the delay after channel selection, since you are using PIC's that allow this to be programmed as part of the read. This is the ADC_TAD_MUL setting. It means the ADC will automatically be allowed to acquire for 8 Tad cycles, before the reading is actually taken.
There is a little problem at the end of the code. When the last loop completes, the PIC will go to sleep. This will happen before the last couple of characters have been sent, so these will be lost.
Now for your problem.
You do not have ERRORS in your RS232 declaration. This is _required_ when using the hardware serial, unless you are manually handling errors yourself. Without this, if two characters are not read, the UART _will_ become hung.
Now I'm guessing you are typing the 'S', but are actually possibly hitting the 'ENTER' afterwards. This normally sends two characters (LF & CR). The code then prints 32 characters, and the UART is not checked at any point, so when you arrive back at the start of the loop, the UART is hung. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Sun Feb 07, 2016 10:12 pm |
|
|
Hi Ttelmah,
Thanks for the valuable advice. I really appreciate your help. I had corrected the code as suggested. The problem I encountered earlier has been resolved. This because in LabVIEW programming I made some errors in the while loop. Now it is OK. In labview I will able to see 64 data (8ch x 8 times) displayed in the front panel. However in continuous mode I could not make the code to loop for another 64 data and so on. Is this related to the pic sleeps after execute the final loop? As I understand the PIC will execute again the while loop and check for the character 'S' has been sent. But this does not occur. |
|
|
|
|
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
|