Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] ATOI command causes program to fail

Status
Not open for further replies.

ghead

Member level 2
Joined
Nov 19, 2010
Messages
43
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,288
Activity points
2,384
HI, I'm trying to read a string from eeprom and use ATOI to convert to a int. Converting int to string and writing to eeprom works fine but when I add the following line the program fails (nothing displays on lcd or any ouputs)

Code C - [expand]
1
arrayFlow[0] = eeprom_read (0x00);



Code C - [expand]
1
2
3
4
arrayFlow[0] = eeprom_read (0x00); //Read target temp value from eeprom
     arrayFlow[1] = eeprom_read (0x01);
     target_temp = atoi(arrayFlow);
     if (target_temp == 0x0ff) {target_temp = 50;}



Full code - ATOI cmd is near the start of void main

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
// LCD module connections
sbit LCD_RS at RD1_bit;
sbit LCD_EN at RD3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;
 
sbit LCD_RS_Direction at TRISD1_bit;
sbit LCD_EN_Direction at TRISD3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
//Output Pins
//sbit led_pin at RA0_bit;
sbit led_heater at RA1_bit;
sbit heater_relay at RA0_bit;
sbit outa at RA2_bit;
//Button Input Pins
sbit button_up at RB0_bit;
sbit button_down at RB1_bit;
sbit button_ok at RB2_bit;
sbit button_swop at RB3_bit;
//SPI pins
sbit spi_sck at RC0_bit;
sbit spi_cs at RC1_bit;
sbit spi_si at RC2_bit;
 
//Variables
bit a, temp_direction;
int target_temp, overshoot;
int tmp_temp, tmp_temp1, last_temp;
short  b, state, button_press_count;
unsigned target_temp1, current_temp;
unsigned int  spi_out;
unsigned char buffer, arrayFlow[5];
//char ii;
 
// Lcd Text
char txt1[] = "TARGET:  ";
char txt2[] = "ACTUAL:  ";
char txt3[] = "OVERSHOOT:";
char txt4[] = "TEMP";
char txt5[] = "CONTROL";
char txt6[] = "***ERROR***";
char txt7[] = ">EDIT<";
char txt8[] = "EDIT";
char txt9[] = "C";
 
void get_current_temp(){
     //;read the value from MAX6675
     //;in some libraries, they suggest performing a "dummy read"
     //;to force the device to re-sample the temperature
     spi_cs = 0;
     Delay_ms(2);
     spi_cs = 1;
     Delay_ms(220);  //;the device should now have a new temperature in its buffer
     spi_cs = 0;  //;enable CS so we can read data back from the device
     Delay_ms(50); //;give the device time to settle
 //    current_temp = spi1_read(buffer) <<8; // upper 8 bit from MAX6675
 //    current_temp|= Spi1_Read(buffer);     // lower 8 bit
 //    current_temp = current_temp <<8; // upper 8 bit from MAX6675
 //    current_temp|= current_temp;     // lower 8 bit
 //    if (current_temp == 0x04){current_temp = 999;}        //;bit 2 is normally low, and goes high when the thermistor is not connected
     current_temp = 400;
     current_temp = current_temp *100;
     current_temp = current_temp / 4; //;bit-shift three places to the right
//      if (current_temp == 0) {          //;something has gone wrong here
//       current_temp = 999;
//       }
 
 
}
 
void show_overshoot(){
     Lcd_cmd(_LCD_CLEAR); //Clear display
     Lcd_out (1,1,txt3);  //Overshoot
     IntToStr(overshoot, arrayFlow);
     Lcd_out(1,11,arrayFlow);
}
 
void show_target_temp(){
     Lcd_cmd(_LCD_CLEAR); //Clear display
     Lcd_out (1,1,txt1);  //Target Temp
     IntToStr(target_temp, arrayFlow);
     Lcd_out(1,11,arrayFlow);
}
 
 
void IntMain() {
 
     TRISA = 0;
     ADCON1 = 6;
     TRISB = 0x0f; //Portb set button input pins
     TRISC = 0x04; //PortC set SPI pins I/O
     PORTA = 0;
     OPTION_REG.B7 = 0;  //enable pullups on portb (RBPU)
     led_heater = 0; //make sure we boot up with the heater off
     heater_relay = 0; //heater indicator is off
     last_temp =0;
     state = 0;
     temp_direction = 0;
     //Turn on SPI
     SSPCON.B5 =1;
     //SPIPrepare       OSC / 16 = 1.25mhz clk  Sample data at MIDDLE   Clk idle Low      SPI receive on clk edge High to Low
     SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV16, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_HIGH_2_LOW);
     spi_cs = 1; //Set cs pin high  SPI device wait(sample)
     spi_sck = 0; //Set sck pin low SPI CLK idle
}
 
void main() {
 
     IntMain();
     Lcd_init();  //Initialise LCD
     Lcd_Cmd(_LCD_CLEAR); // Clear display
     Lcd_Cmd(_LCD_CURSOR_OFF); //no cursor on the lcd display
     Lcd_Out(1,7,txt4);   //TEMP
     Lcd_Out(2,6,txt5);   //CONTROL
     Delay_ms(2000);
     arrayFlow[0] = eeprom_read (0x00); //Read target temp value from eeprom
     arrayFlow[1] = eeprom_read (0x01);
     target_temp = atoi(arrayFlow);    /////////////////////////////////////////////////This cmd causing program to fail????///////////////////////////////////
     if (target_temp == 0x0ff) {target_temp = 50;}
     overshoot = eeprom_read (0x10); //Read overshoot value from eeprom
     if (overshoot == 0x0ff) {overshoot = 10;}
 
 
   while (1){
 
      switch (state) {
 
           
         case 0: //show the target and current temperature(s)
         get_current_temp();
         target_temp1 = target_temp * 100;
         Delay_ms (10);
         Lcd_cmd(_LCD_CLEAR); //Clear display
         Lcd_out (1,1,txt1);   //TARGET:
         IntToStr(target_temp1, arrayFlow);
         Lcd_Chr_Cp(arrayFlow[1]);
         Lcd_Chr_Cp(arrayFlow[2]);
         Lcd_Chr_Cp(arrayFlow[3]);
         Lcd_Chr_Cp('.');
         Lcd_Chr_Cp(arrayFlow[4]);
         Lcd_Chr_Cp(arrayFlow[5]);
         Lcd_out (1,16,txt9);   //C
         Lcd_out (2,1,txt2);   //ACTUAL:
         IntToStr(current_temp, arrayFlow);
         Lcd_Chr_Cp(arrayFlow[1]);
         Lcd_Chr_Cp(arrayFlow[2]);
         Lcd_Chr_Cp(arrayFlow[3]);
         Lcd_Chr_Cp('.');
         Lcd_Chr_Cp(arrayFlow[4]);
         Lcd_Chr_Cp(arrayFlow[5]);
         Lcd_out (2,16,txt9);   //C
         Delay_ms(1000);
         state = 1;
         break;
 
 
         case 1: //;monitor the current temp and the target temp
         get_current_temp();
         tmp_temp1 = current_temp / 100;
         tmp_temp = target_temp - overshoot;
         
         if (tmp_temp1 == 999) {    //Error check
            heater_relay = 0;    //;something has gone wrong
            led_heater = 0;
            Lcd_cmd(_LCD_CLEAR); //Clear display
            Lcd_out (2,3,txt6);  // ERROR
         }
 
         if (last_temp <= tmp_temp1) {temp_direction = 1;}   //temperature is rising
         else  temp_direction = 0; //temperature is falling
 
         if (tmp_temp1 > target_temp) {
            heater_relay = 0; //we're over the target temperature so shut the heaters off
            led_heater = 0;
         }
 
         if (tmp_temp1 > tmp_temp) {
            led_heater = 0;     //;threshold exceeded, turn off the heater(s)
            heater_relay = 0;
         }                         //temperature is rising
         else  {
            led_heater = 1;
            heater_relay = 1;
         }                         //;still not quite there, keep the heaters on
 
         if (tmp_temp1 < tmp_temp) {
            heater_relay = 1;   //;weve cooled down too much, turn the heaters on again
            led_heater = 1;
         }
         else {
            heater_relay = 0;   //;were cooling down, but are still pretty close to the target
            led_heater = 0;     //;temperature, so allow a little more cooling
            last_temp = current_temp;
         }
         //;now while the temperature is being monitored, check for button presses
         //;(on a button press, turn off the heater(s) just for good measure, and
         //;go to a new state just for handling changing the settings
 
         if ((button_up == 0)||(button_down == 0)||(button_ok == 0)) {
            heater_relay = 0;
            led_heater  = 0;
            Delay_ms(50);
            while ((button_up == 0)||(button_down == 0)||(button_ok == 0)) {
               Delay_ms(50); //;wait f the button to be released
            }
         state = 2;
         }
         //Delay_ms(1000);
         break;
 
 
         case 2: //;press buttons to change menu option
         Lcd_cmd(_LCD_CLEAR); //Clear display
         Lcd_out (1,1,txt1);   //Target Temp
         Lcd_out (1,11,txt7);   //>Edit<
         Lcd_out (2,1,txt3);   //OVERSHOOT
         Lcd_out (2,12,txt8);   //Edit
         state = 3;
         break;
 
         case 3:
         if ((button_up == 0)||(button_down == 0)) {
            Delay_ms(50);
            while ((button_up == 0)||(button_down == 0)) {
               Delay_ms (50); //;wait f the button to be released
            }
         state = 4;
         }
 
         if (button_ok == 0) {
            Delay_ms(50);
            while (button_ok == 0) {
               Delay_ms(50); //;wait f the button to be released
            }
            a = 0;
            state = 6;
         }
         break;
 
 
         case 4: //;press buttons to change menu option
         Lcd_cmd(_LCD_CLEAR); //Clear display
         Lcd_out (1,1,txt1);   //TARGET:
         Lcd_out (1,12,txt8);   // EDIT
         Lcd_out (2,1,txt3);   //Overshoot
         Lcd_out (2,11,txt7);   //>EDIT<
         state = 5;
         break;
 
 
         case 5:
         if ((button_up == 0)||(button_down == 0)) {
            Delay_ms(50);
            while (button_up == 0) (button_down == 0);{ Delay_ms(50); }//;wait for the button to be released
            state = 2;
         }
 
         if (button_ok == 0) {
            Delay_ms(50); //;debounce the button press
            while (button_ok == 0) {Delay_ms(50);}
            a = 1;
            state = 6;
         }
         break;
 
 
         case 6: //;change the target and overshoot temperature value
         if (a == 0) {
            show_target_temp();
            state = 7;
         }
         if (a == 1) {
            show_overshoot();
            state = 7;
         }
         break;
 
 
         case 7: //;button presses to alter target temperature/overshoot value
         if (button_up == 0) {
            Delay_ms(50);
            button_press_count = 0;
            while (button_up == 0) {
               //;wait for the button to be released
               button_press_count = button_press_count + 1;
               Delay_ms(100);
               if (button_press_count >= 5) {
                  if (a == 0) {
                     if (target_temp < 320) { target_temp = target_temp + 10; }
                     else target_temp = 320;
                     show_target_temp();
                  }
                  else {
                     if (overshoot < 320) { overshoot = overshoot + 10; }
                     else overshoot = 320;
                     show_overshoot();
                  }
                  Delay_ms(200);
                  //;stop the counter from rolling over
               button_press_count = 5;
               }
               if (button_press_count < 5) {
                  if (a==0) {
                     if (target_temp < 320) {Target_temp = target_temp + 1;}
                     else target_temp = 320;
                     show_target_temp();
                  }
                  if (a==1) {
                     if (overshoot < 320) {overshoot = overshoot + 1;}
                     else overshoot = 320;
                     show_overshoot();
                  }
               }
            }
            state = 7;
         }
 
         if (button_down == 0) {
            Delay_ms(50);
            button_press_count = 0;
            while (button_down == 0) {
               //;wait for the button to be released
               button_press_count = button_press_count + 1;
               Delay_ms(100);
               if (button_press_count >= 5) {
                  if (a == 0) {
                     if (target_temp > 10) { target_temp = target_temp - 10; }
                     else target_temp = 0;
                     show_target_temp();
                  }
                  else {
                     if (overshoot > 10) { overshoot = overshoot - 10; }
                     else overshoot = 0;
                     show_overshoot();
                  }
                  Delay_ms(200);
                  //;stop the counter from rolling over
               button_press_count = 5;
               }
               if (button_press_count < 5) {
                  if (a==0) {
                     if (target_temp > 1) {Target_temp = target_temp - 1;}
                     else target_temp = 0;
                     show_target_temp();
                  }
                  if (a==1) {
                     if (overshoot > 1) {overshoot = overshoot - 1;}
                     else overshoot = 0;
                     show_overshoot();
                  }
               }
            }
            state = 7;
         }
 
         if (button_ok == 0) {
            Delay_ms(50); //;simple debounce
            while (button_ok == 0) {Delay_ms(50);} //;wait for button to be released
            if (a == 0) {
               b = target_temp;     // Load target temp into write file
               IntToStr(target_temp, arrayFlow);
               eeprom_write (0x00,arrayFlow[0]); //;write the new target temp to eeprom
               eeprom_write (0x01,arrayFlow[1]); //;write the new target temp to eeprom
            }
            if (a == 1) {
               b = overshoot;      // Load target temp into write file
               eeprom_write (0x10,b); //;write the new overshoot value to eeprom
            }
            state = 0;
         }
         break;
      }
 
   }
}

 

unsigned char buffer, arrayFlow[5];
This is wrong.

Run up mikroC IDE and put your cursor anywhere within the text "IntToStr" within your program, then press F1 key to get help. You will see that your arrayFlow array size is too small.

Code:
           while (button_up == 0) (button_down == 0);{ Delay_ms(50); }//;wait for the button to be released
Not sure what you intended here, but that code looks wrong to me.

Code:
               IntToStr(target_temp, arrayFlow);
               eeprom_write (0x00,arrayFlow[0]); //;write the new target temp to eeprom
               eeprom_write (0x01,arrayFlow[1]); //;write the new target temp to eeprom
Can't make sense of this. You create a 7 byte string and then only store 2 bytes to EEPROM, which for small numbers will simply be 2 space characters.
I suspect you want to store the 2 byte integer target_temp, not an ASCII string.
 
Last edited:
  • Like
Reactions: ghead

    ghead

    Points: 2
    Helpful Answer Positive Rating
I'm using arrayFlow for other operations and was trying to save declaring another array when I already have one declared. Maybe not the right thing to do but as this device has limited ram.
For the other functions arrayFlow is being used it works fine (I changed size from [7] to [5] to save space and that part of program still runs fine as far as testing proved)
I seemed to have missed adding '||' between expressions in the while loop (program seems to work when that part was tested)
Yes I want to store as a 2 byte integer and return and the same format int it seems i've gone about it the wrong way.
 

Presumed you are actually reading the temperature as decimal string from the EEPROM, consider that strings need a terminating null character to be understood e.g. by atoi(). If you don't store and read the null in/from EEPROM, it must be "patched" into the char array. Most people would however store binary values in EEPROM, no need for conversions then.
 
  • Like
Reactions: ghead

    ghead

    Points: 2
    Helpful Answer Positive Rating
I changed size from [7] to [5] to save space

:thumbsdown:
 

I'm Reading the temperature via spi device and displaying it on lcd and controlling fan or heater with target temp and overshoot values . The values being stored are for the target temperature and an overshoot value, Both with a 0 - 500 decimal range.

So i would be better reading the hi byte then bit shifting it left and adding lower byte to it?
I tried this earlier when writing to epprom but was causing program to fail in much the same way, I cant seem to figure out why except maybe the stack depth being compromised.
 

0 to 500 requires two bytes because each can only hold values up to 255.
You can store it as two bytes using the modulo operator and combine them for the result by adding 256*high byte to the low byte or by shifting the high byte 8 bits to the left then adding or ORing the low byte.

The easiest way to save a string to EEPROM is to use a 'union'. All you have to do is define a union and inside it define the character array and also a byte array. Inside a union, the two share the same address space (they overlap) so you can write in the units of one and read in the units of the other. In this case, save your string, int or whatever you decide to use as one of the variables then use the byte sized one to save it in EEPROM.

Example from one of my projects where several two unsigned long variables (stored as 4 bytes each) and two byte values are stored as ten consecutive EEPROM locations called EE[0] to EE[9]:
Code:
union
{
    struct
    {
        ulong    RF_Freq;            // 4 bytes
        ulong Offset_Freq;    // 4 bytes
        BYTE OffsetMode;        // 1 byte
        BYTE SelectedStep        // 1 byte
    }sn;
    BYTE EE[10];
}un;

I have unsigned longs typecast as ulong and char typecast as BYTE in that example.

Brian.
 
  • Like
Reactions: ghead

    ghead

    Points: 2
    Helpful Answer Positive Rating
So something like this for write

Code C - [expand]
1
2
3
4
5
{
                  union U16_ Int2Bytes;
                  Int2Bytes.word = target_temp;
                  eeprom_write (0x00,Int2Bytes.byte[1]);  // write the hi byte
                  eeprom_write (0x01,Int2Bytes.byte[0]);  // write the lo byte to eeprom



and for reading

Code C - [expand]
1
2
3
4
5
6
7
8
buffer1 = eeprom_read (0x00);
     buffer = eeprom_read (0x01);
{
union U16_ Bytes2Int;
             Bytes2Int.byte[1] = buffer1;  //  combine bytes
             Bytes2Int.byte[0] = buffer;  //
              target_temp = Bytes2Int.word; // return the combined bytes as a 16-bit word
}

 

Not quite.

union
{
Int Variable;
char EEBytes[2];
}YourUnionName;

Now if you put a 16 bit value in 'Variable', (which takes two bytes to store) you can read it as two 8-bit values in EEByte[0] and EEByte[1]. All the union does is store it's component parts in overlapping memory but it is useful because it allows you to break down larger storage types into smaller ones, in this case a 16 bit integer into two 8 bit bytes without doing any math or logic functions.

A good tutorial on unions and structures which are very similar will help you.

Brian.
 
  • Like
Reactions: ghead

    ghead

    Points: 2
    Helpful Answer Positive Rating
I'm not quite understanding, Do you mean i've got the syntax wrong and should be more like this
setup

Code C - [expand]
1
2
3
4
5
union U16_
{
   unsigned int word;      // For accessing the whole 16-bit unsigned int///////
   unsigned char byte[2];  // For accessing 16-bits as individual bytes/////////
};


Combine after reading eeprom

Code C - [expand]
1
2
3
4
5
union { 
                     Bytes2Int.byte[1] = buffer1;        //combine MSB's with LSB's
                    Bytes2Int.byte[0] = buffer0;
                    current_temp = Bytes2Int.word;     //combined bytes as a 16-bit word
               }U16_ Bytes2Int;


And write to eeprom

Code C - [expand]
1
2
3
4
5
union {
                                 Int2Bytes.word = overshoot;
                                 eeprom_write (0x11,Int2Bytes.byte[1]);  // write the hi byte
                                 eeprom_write (0x10,Int2Bytes.byte[0]);  // write the lo byte to eeprom
                            }U16_ Int2Bytes;




This is how its currently in my code and appears to be working (not all in row like shown)


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
union U16_
{
   unsigned int word;      // For accessing the whole 16-bit unsigned int///////
   unsigned char byte[2];  // For accessing 16-bits as individual bytes/////////
};
    { 
    union 
     U16_ Bytes2Int;
        Bytes2Int.byte[1] = buffer1;        //combine MSB's with LSB's
        Bytes2Int.byte[0] = buffer0;
        current_temp = Bytes2Int.word;     //combined bytes as a 16-bit word
     }
     {
    union U16_ Int2Bytes;
                  Int2Bytes.word = overshoot;
                  eeprom_write (0x11,Int2Bytes.byte[1]);  // write the hi byte
                  eeprom_write (0x10,Int2Bytes.byte[0]);  // write the lo byte to eeprom
      }

 

Exactly - all the union does is store all the individual contents in the same physical location so you can refer to it in different ways. In your case saving an int requires 16 bits and because the same space can be read as individual bytes you can access the high and low bytes as individual 8 bit values as needed by the EEPROM.

If you look at the example I used in post #7, I stored two unsigned long (32 bit) values and two chars (8 bit) values and then can access them as ten 8 bit values. With integers it is fairly easy to do the same thing by masking and shifting bits to break the 16 bits into two halves but when you use floats and longs, the math become much more complicated so the union method, which works with all data types, is the better option.

Note that where you store 'Int2Bytes.byte[]' you can save some typing by declaring it as a two byte array in the union then referring to it by its index elsewhere ([0] or [1]). This is because the union can hold any data type, including arrays, there is no need to type both lines into the union.

This is the full code for my Signal generator using a cheap DDS module, two line LCD and a 4x4 keypad. It is written for a PIC 16F628A and uses the WizC-Pro compiler so so functions may be unfamiliar but you should be able to see how it manipulates the 32 bit frequency values and stores them in EEPROM as settings are changed and also reads them from EEPROM at start up. It is so it retains settings when powered down and up again.

Code:
#include "Y:\\projects\\DDS3\\DDS3_Auto.h"
#include <stdlib.h>
#include <strings.h>
#include <delays.h>

#define COUNT_PER_HZ    34.35973873 // delta phase to change f by 1Hz
#define RX 0
#define TX 1

#eeprom 0 = 0x40,0x42,0x0F,0x00        // 1000000 default frequency
#eeprom 4 = 0x58,0xF1,0x06,0x00        // 455000 default offset
#eeprom 8 = 0x00                                    // no offset
#eeprom 9 = 0x02                                    // step size 100Hz
#eeprom 10 = 'D','D','S','3','(','C',')','G','W','6','B','W','X'
#eeprom 23 = 0,0,0,0,0,0,'.',2,0,1,8,'-',0,1,'-',0,6

char Initialised = 0;
ulong New_Freq = 0;
unsigned long DeltaPhase; // = 0;
int StepSize; // = 100;

char LCDBuffer[20];
char Mode = TX;
char EEPtr;

const char KeyTranslate[16] = {0x01,0x02,0x03,0x0A,0x04,0x05,0x06,0x0B,0x07,0x08,0x09,0x0C,0x0E,0x00,0x0F,0x0D};
const char OffsetType[3][5] = {"None","+","-"};
const int StepSizes[5] = {1,10,100,1000,10000};

void Init_DDS_LCD();
void Write9850(unsigned long Frequency);
void KeyPressed();

void SetOffsetMode();
void UpdateLCD();
void SaveToEE();
void RXMode();
void TXMode();

union
{
    struct
    {
        ulong    RF_Freq;            // 4 bytes
        ulong Offset_Freq;    // 4 bytes
        BYTE OffsetMode;        // 1 byte
        BYTE SelectedStep        // 1 byte
    }sn;
    BYTE EE[10];
}un;

//*******************************************************************************
//
void UserInterrupt()
{
    // Insert your code here

 #asmline SETPCLATH UserIntReturn,-1  ; SETPCLATH for interrupt routine
 #asmline goto UserIntReturn          ; Assembler - go back to interrupt routine
}


//*******************************************************************************
//
// Insert your initialisation code if required here. 
// Note that when this routine is called Interrupts will not be enabled - the 
// Application Designer will enable them before the main loop
//

void UserInitialise()
{
    OPTION_REG |= (1 << NOT_RBPU);
    T1CON &= ~(1 << TMR1ON);        // stop the timer
}

//*******************************************************************************
//
// Insert your main loop code if required here. This routine will be called
// as part of the main loop code
//

void UserLoop()
{
    if(Initialised == 0) 
    {
        Init_DDS_LCD();
        T1CON = 0x20;  // 1:4, internal clock, disabled
        Initialised = 1;
    }
    
    if((TXRX == 0) && (Mode == RX))
    {
        Mode = TX;
        TXMode();
        UpdateLCD();
    }
    else if((TXRX == 1) && (Mode == TX))
    {
        Mode = RX;
        RXMode();
        UpdateLCD();
    }
    
}

//*******************************************************************************
//
void Init_DDS_LCD()
{
    EEPtr = 10; //sizeof(u_name);
    
    LCDOnOff(1,1,1);
    LCDClear();
    // set up AD8950 registers
  WCLK9850 = 0;            // make clock line low
    FU9850 = 0;                // make update line low
    FU9850 = 1;                // enable serial mode
    FU9850 = 0;
    
    while(EEPtr--) un.EE[EEPtr] = ReadEEData(EEPtr);
    StepSize = StepSizes[un.sn.SelectedStep];

    Write9850(un.sn.RF_Freq);

    UpdateLCD();

}


//*****************************************************************************
void Write9850(unsigned long Frequency)
{
    unsigned long F_BitMask = 1;
    char BitPtr = 32;
    
    DeltaPhase = (float)Frequency * COUNT_PER_HZ;
    
    // frequency control words first
    while(BitPtr--)
    {
        DATA9850 = (DeltaPhase & F_BitMask) > 0?1:0;
        F_BitMask <<= 1;
        WCLK9850 = 1;        // accepts data on rising edge
        WCLK9850 = 0;
    }
    
    // then control and phase word 
    BitPtr = 8;
    DATA9850 = 0;
    while(BitPtr--)
    {
        WCLK9850 = 1;        // accepts data on rising edge
        WCLK9850 = 0;
    }
    
    // finally send update signal to AD9850
    FU9850 = 1;
  FU9850 = 0;
}

//*****************************************************************************
void KeyPressed()
{
    char KeyNumber = KeyTranslate[KP4Value];
    
    if(KeyNumber < 0x0A)
    {
        New_Freq *= 10;
        New_Freq += KeyNumber;
    }
    
    else
    {
        if(KeyNumber == 0x0A)                                // up 100Hz
        {
            un.sn.RF_Freq += StepSize;
            Write9850(un.sn.RF_Freq);
        }
      
      if(KeyNumber == 0x0B)                                // down 100Hz    
        {
            un.sn.RF_Freq -= StepSize;
            Write9850(un.sn.RF_Freq);
        }

        if(KeyNumber == 0x0C)                                // select step size
        {
            un.sn.SelectedStep++;
            if(un.sn.SelectedStep > 4) un.sn.SelectedStep = 0;
            StepSize = StepSizes[un.sn.SelectedStep];
        }

        if(KeyNumber == 0x0D)                             // set offset mode (none, - or +)
        {
            un.sn.OffsetMode++;
            SetOffsetMode();
        }

        if(KeyNumber == 0x0E)                                // set frequency
        {
            un.sn.RF_Freq = New_Freq;
            Write9850(un.sn.RF_Freq);
        }

        if(KeyNumber == 0x0F)                                // set offset                              
        {
            un.sn.Offset_Freq = New_Freq;
      }

      New_Freq =0;
      
        TMR1H = 0x0B;  TMR1L = 0xDC;    // roll over in ~400mS
        T1CON |= (1 << TMR1ON);  
        
//        SaveToEE();    
    }
    
    UpdateLCD();
    
    
}

//*****************************************************************************
void SetOffsetMode()
{
    if(un.sn.OffsetMode > 2) un.sn.OffsetMode = 0;
    if(un.sn.OffsetMode == 0) Write9850(un.sn.RF_Freq);
    else if (un.sn.OffsetMode == 1) Write9850(un.sn.RF_Freq + un.sn.Offset_Freq);
    else if (un.sn.OffsetMode == 2) Write9850(un.sn.RF_Freq - un.sn.Offset_Freq);
}    

//*****************************************************************************


//*****************************************************************************
void UpdateLCD()
{
    LCDClear();
    
    LCDPrintAt(0,0);
  LCDString("Freq:");
  lPrtString(LCDBuffer,un.sn.RF_Freq);
  LCDString(LCDBuffer);

    LCDPrintAt(0,1);
    LCDString("New:");
     lPrtString(LCDBuffer,New_Freq);
     LCDString(LCDBuffer);

    LCDPrintAt(20,0);
    LCDString("Step:");
    lPrtString(LCDBuffer,un.sn.SelectedStep[StepSizes]);
    LCDString(LCDBuffer);
    if(Mode == TX) LCDString(" [TX]");
    
  LCDPrintAt(20,1);
     LCDString("Offset:");
     LCDString(OffsetType[un.sn.OffsetMode]);
    if(un.sn.OffsetMode) 
    {
        lPrtString(LCDBuffer, un.sn.Offset_Freq);
      LCDString(LCDBuffer);
  }
}  

//*****************************************************************************
void TXMode()
{
    Mode = TX;
    Write9850(un.sn.RF_Freq);
}

//*****************************************************************************
void RXMode()
{
    Mode = RX;
    SetOffsetMode();
}

//*****************************************************************************
void SaveToEE()
{
    T1CON &= ~(1 << TMR1ON);        // stop the timer
    EEPtr = 10;
    while(EEPtr--)
    {
        WriteEEData(EEPtr,un.EE[EEPtr]);
        Wait(10);
    }
}

Brian.</delays.h></strings.h></stdlib.h>
 
  • Like
Reactions: ghead

    ghead

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top