Forum: Mikrocontroller und Digitale Elektronik Si4705 und C8051F321 kommunizieren nicht


von Thomas T. (truthz03)


Angehängte Dateien:

Lesenswert?

Hallo,

ich arbeite gerade an einem eingenen Radio mit Hilfe des Si4705 Chips 
von Silab.
Zur Kommunikation zwischen dem Si4705 und dem PC dient der C8051F321 
MCU.
Um den Si4705 Chip einstellen zu können, kommuniziert der MCU mit diesem 
über eine 2-wire, 3-wire oder SPI Schnittstelle (einstellbar).

Mein Problem ist, dass die Komunikation scheinbar nicht funktioniert, da 
keiner meiner Befehle funktioniert.
Erschwerend kommt hinzu, dass ich noch nie mit einem C8051 gearbeitet 
habe.

Hier der entscheidente Testcode von Silab, der leicht von mir 
modifiziert wurde:
1
//-----------------------------------------------------------------------------
2
// F320_FM_RadioMain.c
3
//-----------------------------------------------------------------------------
4
// Copyright 2006 Silicon Laboratories, Inc.
5
// http://www.silabs.com
6
//
7
// Program Description:
8
//
9
// This is the main project module.  It initializes all system hardware, and 
10
// then enables interrupts.  All further processing is done in the various
11
// interrupt handlers.
12
//
13
// Linker options are used to absolutely locate code to specific locations.
14
//
15
// The linker option can be viewed from the Tool Chain Integration window
16
// Project -> Tool Chain Integration -> Linker (tab)
17
//
18
// FID:            32X000042
19
// Target:         C8051F320
20
// Tool chain:     KEIL C51 7.0.0.1
21
//                 Silicon Laboratories IDE version 2.3
22
// Command Line:   See Readme.txt
23
// Project Name:   F320_FM_Radio
24
//
25
// Release 1.1
26
//    -Changed Oscillator_Init to start clock multiplier correctly (DM)
27
//    -16 JAN 2006
28
//
29
// Release 1.0
30
//    -Initial Revision (DM)
31
//    -05 AUG 2005
32
//
33
34
//-----------------------------------------------------------------------------
35
// Includes
36
//-----------------------------------------------------------------------------
37
38
#include "c8051f320.h"                 // SFR declarations
39
#include "F320_FM_RadioMain.h"         // Main project header
40
#include "F320_Si470x_Interface.h"     // Si470x interface header
41
#include "io.h"
42
43
#define IO3W    0
44
#define IO2W    1
45
46
#define CTS     0x80
47
#define GET_REV 0x10
48
#define POWER_UP                      0x01
49
#define POWER_UP_IN_FUNC_FMRX         0x00
50
#define POWER_UP_IN_FUNC_AMRX         0x01
51
#define POWER_UP_IN_FUNC_FMTX         0x02
52
#define POWER_UP_IN_FUNC_WBRX         0x03
53
#define POWER_UP_IN_FUNC_QUERY        0x0F
54
#define POWER_UP_IN_PATCH             0x20
55
#define POWER_UP_IN_GPO2OEN           0x40
56
#define POWER_UP_IN_CTSIEN            0x80
57
#define POWER_UP_IN_OPMODE_RX_ANALOG  0x05
58
#define POWER_UP_IN_OPMODE_TX_ANALOG  0x50
59
#define GET_INT_STATUS 0x14
60
61
#define POWERUP_TIME 110
62
63
u8 io_mode = IO3W;
64
65
u8  idata cmd[8];
66
u8  idata rsp[15];
67
68
void si47xx_getPartInformation();
69
70
//-----------------------------------------------------------------------------
71
// main
72
//
73
// Return Value : None
74
// Parameters   : None
75
//
76
// Main program routine.
77
//
78
//-----------------------------------------------------------------------------
79
void main (void)
80
{
81
  int j=0;
82
83
  data WORD Temp;
84
  data WORD Temp2;
85
86
87
   PCA0MD &= ~0x40;                    // Disable Watchdog timer
88
   VDM0CN |= 0x80;                     // Enable the VDD Monitor
89
90
   // Configure comparator0 and crystal drive
91
   Crystal_Init ();
92
93
   // Initialize SPI0, should be before crossbar enable
94
   SPI0_Init ();                               
95
96
   Timer0_2_Init ();                   // Initialize timers
97
   PCA0_Init ();                       // Initialize PCA module (USB)
98
   Port_Init ();                       // Initialize crossbar and GPIO
99
100
   // Select VDD Monitor as a Reset Source
101
   RSTSRC = 0x02; 
102
   
103
104
  si47xx_getPartInformation();
105
106
107
   EA = 1;                             // Global Interrupt enable
108
   
109
   while (1);                          // Spin forever
110
}
111
112
//-----------------------------------------------------------------------------
113
// Initialization Subroutines
114
//-----------------------------------------------------------------------------
115
116
//-----------------------------------------------------------------------------
117
// Oscillator_Init
118
//-----------------------------------------------------------------------------
119
//
120
// Return Value : None
121
// Parameters   : None
122
//
123
// This function initializes the clock multiplier and selects it as the system
124
// clock.
125
//
126
//-----------------------------------------------------------------------------
127
void Oscillator_Init (void)
128
{
129
   // Configure internal oscillator for its maximum frequency and enable
130
   // missing clock detector
131
   OSCICN |= 0x03;
132
133
   // Select internal oscillator as input to clock multiplier
134
   CLKMUL = 0x00;                        
135
136
   CLKMUL |= 0x80;                     // Enable clock multiplier
137
   Delay_Main ();                      // Delay for clock multiplier
138
   CLKMUL |= 0xC0;                     // Initialize the clock multiplier
139
140
   while (!(CLKMUL & 0x20));           // Wait for multiplier to lock
141
   CLKSEL = SYS_4X_DIV_2;              // Select 24 MHz clock as sysclock
142
}
143
144
//-----------------------------------------------------------------------------
145
// Crystal_Init
146
//-----------------------------------------------------------------------------
147
//
148
// Return Value : None
149
// Parameters   : None
150
//
151
// This function starts the crystal drive circuit and configures the comparator
152
// to operate as a clock buffer for Si470x.
153
//
154
//-----------------------------------------------------------------------------
155
void Crystal_Init (void)
156
{
157
   // Turn on crystal drive circuit for 32.768 kHz crystal
158
   OSCXCN = 0x61;
159
160
   CPT0CN = 0x85;                      // Turn on comparator 0, 5 mV hysteresis
161
   CPT0MX = 0x00;                      // Negative = P1.1, Positive = P1.0
162
   CPT0MD = 0x00;                      // Response time = 100 ns
163
}
164
165
//-----------------------------------------------------------------------------
166
// SPI0_Init
167
//-----------------------------------------------------------------------------
168
//
169
// Return Value : None
170
// Parameters   : None
171
//
172
// This function configures the SPI for Si470x.
173
//
174
//-----------------------------------------------------------------------------
175
void SPI0_Init (void)
176
{
177
   // Clock idle high, Data centered on 2nd edge, SPI master
178
   SPICFG = 0x70;
179
   SPI0CN = 0x83;                      // Enable SPI, 3-wire mode selected
180
181
   // Configure SPI clock rate for 2.4 MHz (Maximux 2.5 MHz for Si470x)
182
   SPICKR = ((SYSCLK / (2400000*2)) - 1);
183
}
184
185
//-----------------------------------------------------------------------------
186
// Port_Init
187
//-----------------------------------------------------------------------------
188
//
189
// Return Value : None
190
// Parameters   : None
191
//
192
// This function configures the Crossbar and GPIO ports.
193
//
194
// P0.2  analog               XTAL1
195
// P0.3  analog               XTAL2
196
//
197
// P1.0  analog               COMPARATOR POSITIVE INPUT
198
// P1.1  analog               COMPARATOR NEGATIVE INPUT
199
// P1.2  digital  push-pull   Si 4701 RESET
200
// P1.3  digital  push-pull   SEN_BAR
201
// P1.4  digital  push-pull   SCLK
202
// P1.5  digital  open-drain  MISO
203
// P1.6  digital  push-pull   MOSI
204
// P1.7  digital  push-pull   RCLK/COMPARATOR OUTPUT
205
//
206
// P2.0  analog               RIGHT AUDIO CHANNEL
207
// P2.1  analog               LEFT AUDIO CHANNEL
208
// P2.3  digital  push-pull   GREEN LED/PCA OUTPUT
209
//
210
// P3.0  digital  push-pull   RED LED
211
//
212
//-----------------------------------------------------------------------------
213
void Port_Init (void)
214
{
215
   P0MDIN = 0x03;                      // Port 0 pins 2-7 analog
216
   P1MDIN = 0xFC;                      // Port 1 pins 0, 1 analog
217
   P2MDIN = 0x0C;                      // Port 2 pins 0, 1, 4-7 analog
218
   P3MDIN = 0x01;                      // Port 3 all digital
219
220
   P0MDOUT = 0x00;                     // Port 0 pins set open-drain
221
   P1MDOUT = 0xDC;                     // Port 1 pins 2-4, 6, 7 set push-pull
222
   P2MDOUT = 0x0C;                     // Port 2 pins 2, 3 set push-pull
223
   P3MDOUT = 0x01;                     // Port 3 pin 1 set push-pull
224
225
   P0SKIP = 0xFF;                      // Port 0 skip pins 0-7
226
   P1SKIP = 0x0F;                      // Port 1 skip pins 0-3
227
   P2SKIP = 0xF7;                      // Port 2 skip pins 0, 1, 2, 4-7
228
229
   P0 = 0x02;                          // Port 0 pins 1 start high
230
   P1 = 0xE3;                          // Port 1 pins 0, 1, 5-7 start high
231
   P2 = 0x03;                          // Port 2 pins 0, 1 start high
232
   P3 = 0x00;                          // Port 3 starts low
233
234
   XBR0 = 0x22;                        // Comparator0, SPI enabled
235
236
   // Enable Crossbar, Weak Pull-ups on, 2 PCA modules are on
237
   XBR1 = 0x42;
238
}
239
240
241
//-----------------------------------------------------------------------------
242
// Timer0_2_Init
243
//-----------------------------------------------------------------------------
244
//
245
// Return Value : None
246
// Parameters   : None
247
//
248
// Initializes timer 2 used for ADC conversion start, and timer 0 used for PCA.
249
//
250
//-----------------------------------------------------------------------------
251
void Timer0_2_Init (void)
252
{
253
   CKCON = 0x02;                       // Prescale bits set to system clock/48
254
   CKCON &= ~0x04;                     // Timer0 uses prescaler defined clock
255
   TMOD = 0x02;                        // Timer0 set to mode 2
256
   TH0 = (-(SYSCLK/48/30000));         // PCA frequency = 30 kHz
257
   TR0 = ON;                           // Start timer 0
258
259
   TMR2CN = 0x00;                      // Stop Timer2; Clear TF2;
260
   CKCON |= 0x10;                      // Timer2 clocked based on system clock
261
   TMR2RL = (-(SYSCLK/192000));        // Initialize reload value for 192000 Hz
262
   TMR2 = 0xFFFF;                      // Set to reload immediately
263
264
   ET2 = 1;                            // Enable Timer2 interrupts
265
   PT2 = ON;                           // Set interrupt to high priority
266
}
267
268
//-----------------------------------------------------------------------------
269
// ADC0_Init
270
//-----------------------------------------------------------------------------
271
//
272
// Return Value : None
273
// Parameters   : None
274
//
275
// Configure ADC for single ended conversions on timer 2 overflows.
276
//
277
//-----------------------------------------------------------------------------
278
void ADC0_Init (void)
279
{
280
   // Disable internal voltage reference VREF, use VDD instead for ADC
281
   REF0CN = 0x0A;
282
283
   AMX0N = 0x1F;                       // Single ended mode (negative = gnd)
284
285
   ADC0CF = 0x3C;                      // SAR clock 3 MHz, left adjusted output
286
287
   // Converion on timer 2 overflow with low power tracking mode off
288
   ADC0CN = 0x82;
289
}
290
291
//-----------------------------------------------------------------------------
292
// PCA_Init
293
//-----------------------------------------------------------------------------
294
//
295
// Return Value : None
296
// Parameters   : None
297
//
298
// Initializes USB0, enable transceiver and USB0 interrupts.
299
//
300
//-----------------------------------------------------------------------------
301
void PCA0_Init (void)
302
{
303
   PCA0CPM0 = 0x42;                    // PCA module 0 in 8-bit PWM Mode
304
   PCA0CPM1 = 0x42;                    // PCA module 1 in 8-bit PWM Mode
305
   PCA0CPM2 = 0x00;                    // PCA module 2 currently unused
306
   PCA0CPM3 = 0x00;                    // PCA module 3 currently unused
307
   PCA0CPM4 = 0x00;                    // PCA module 4 currently unused
308
309
   // PCA module 0 starts with minimum duty cycle for all pulses
310
   PCA0CPL0 = 0xFF;
311
   PCA0CPH0 = 0xFF;
312
313
   // PCA module 1 starts with minimum duty cycle for all pulses
314
   PCA0CPL1 = 0xFF;
315
   PCA0CPH1 = 0xFF;
316
317
   // PCA timer uses timer 0 overflows and runs when CPU is idle
318
   PCA0MD = 0x04;
319
   PCA0CN = 0x40;                      // PCA timer running, interrupts cleared
320
}
321
322
//-----------------------------------------------------------------------------
323
// Delay_Main
324
//-----------------------------------------------------------------------------
325
//
326
// Return Value : None
327
// Parameters   : None
328
//
329
// Used for a 500 microsecond pause during hardware configuration.
330
// There are two identical versions of this routine, one for the main program
331
// and another for the USB interrupt.  This version is for the main program.
332
// (assuming 24 MHz system clock)
333
//
334
//-----------------------------------------------------------------------------
335
void Delay_Main (void)
336
{
337
   data volatile int x;
338
   for (x = 0;x < 500;x)
339
      x++;
340
}
341
342
//-----------------------------------------------------------------------------
343
// End Of Basicfunctions
344
//-----------------------------------------------------------------------------
345
346
347
348
void wait_us(u16 us)
349
{
350
    u16 j;
351
352
    j = 65535u - 24 * us;
353
    TL0 = j;         // Load Timer 0 low byte
354
    TH0 = j >> 8;    // Load Timer 0 high byte
355
    TR0 = 1;         // Enable Timer 0
356
    TF0 = 0;         // Clear Timer 0 Overflow flag
357
358
    while(TF0 != 1); // Wait for Timer 0 to overflow
359
360
    TR0 = 0;         // Disable Timer 0
361
    TF0 = 0;         // Clear Timer 0 Overflow Flag
362
}
363
364
void wait_ns(u16 ns)
365
{
366
    u8 i;
367
368
    for ( i = 1; i <= ns / 32; i++ )
369
    ;
370
}
371
372
void wait_ms(u16 ms)
373
{
374
    int i;
375
376
    for ( i = 0; i < ms; i++ ) {
377
        wait_us(1000);
378
    }
379
}
380
381
void si47xx_lowWrite(u8 number_bytes, u8 idata *data_out)
382
{
383
    if(io_mode == IO3W)
384
    {
385
        io3w_write(number_bytes, data_out);
386
    }
387
    else // IO2W
388
    {
389
        io2w_write(number_bytes, data_out);
390
    }
391
}
392
393
void si47xx_lowRead(u8 number_bytes, u8 idata *data_in)
394
{
395
    if(io_mode == IO3W)
396
    {
397
        io3w_read(number_bytes, data_in);
398
    }
399
    else // IO2W
400
    {
401
        io2w_read(number_bytes, data_in);
402
    }
403
}
404
405
u8 si47xx_readStatus()
406
{
407
    u8 status;
408
   
409
    si47xx_lowRead(1, &status);
410
411
    return status;
412
}
413
414
void si47xx_waitForCTS()
415
{
416
  int temp=0;
417
    u16 i=1000;
418
419
    // Loop until CTS is found or stop due to the counter running out.
420
    while (--i && !(si47xx_readStatus() & CTS))
421
    {
422
        wait_us(500);
423
    }
424
425
  temp=1;
426
  temp=2;
427
428
    // If the i is equal to 0 then something must have happened.
429
    // It is recommended that the controller do some type of error
430
    // handling in this case.
431
}
432
433
//-----------------------------------------------------------------------------
434
// Sends a command to the part and returns the reply bytes
435
//-----------------------------------------------------------------------------
436
void si47xx_command(u8 cmd_size, u8 idata *cmd, u8 reply_size, u8 idata *reply)
437
{
438
    // It is always a good idea to check for cts prior to sending a command to
439
    // the part.
440
    si47xx_waitForCTS();
441
442
    // Write the command to the part
443
    si47xx_lowWrite(cmd_size, cmd);
444
445
    // Wait for CTS after sending the command
446
    si47xx_waitForCTS();
447
448
    // If the calling function would like to have results then read them.
449
    if(reply_size)
450
    {
451
        si47xx_lowRead(reply_size, reply);
452
    }
453
}
454
455
void si47xx_getPartInformation(void)
456
{
457
  data WORD Temp;
458
  data WORD Temp2;
459
460
  u8 partNumber;
461
  char fwMajor;
462
  char fwMinor;
463
  u16  patchID;
464
  char cmpMajor;
465
  char cmpMinor;
466
  char chipRev;
467
  char status=0xab;
468
469
  cmd[0]=0x0;
470
  cmd[1]=0x0;
471
  cmd[2]=0x0;
472
  cmd[3]=0x0;
473
  cmd[4]=0x0;
474
  cmd[5]=0x0;
475
  cmd[6]=0x0;
476
  cmd[7]=0x0;
477
478
  rsp[0]=0xee;
479
  rsp[1]=0xee;
480
  rsp[2]=0xee;
481
  rsp[3]=0xee;
482
  rsp[4]=0xee;
483
  rsp[5]=0xee;
484
  rsp[6]=0xee;
485
  rsp[7]=0xee;
486
  rsp[8]=0xee;
487
  rsp[9]=0xee;
488
  rsp[10]=0xee;
489
  rsp[11]=0xee;
490
  rsp[12]=0xee;
491
  rsp[13]=0xee;
492
  rsp[14]=0xee;
493
494
495
496
497
  Delay_Main ();
498
499
   // Wait for crystal to stabilize, make sure crystal has been running 1 ms
500
   while ((OSCXCN & 0x80) == 0);              
501
502
   // Make sure crystal frequency is stable
503
   for (Temp.i = 0; Temp.i < 200; Temp.i++) 
504
     Delay_Main ();
505
506
   RADIO_RESET = ON;                   // Bring radio out of reset
507
   SEN_bar = ON;  
508
509
510
  CONTROL_READ (POWERCONFIG, Temp);
511
   Temp.i &= ~DISABLE_PC;
512
   Temp.i |= ENABLE_PC;
513
   CONTROL_WRITE (POWERCONFIG, Temp);  // Enable radio
514
515
516
   for (Temp.i = 0; Temp.i < 1000; Temp.i++) Delay_Main ();
517
518
519
520
  // NOTE:  This routine should only be called when the part is powered up.
521
  // If you wish to retrieve some of the part information without fully
522
  // powering up the part call the POWER_UP command on the part with the
523
  // FUNC_DEBUG flag.
524
525
  // Put the ID for the command in the first byte.
526
  cmd[0] = GET_REV;
527
528
  // Invoke the command
529
  si47xx_command(1, cmd, 9, rsp);
530
531
  // Now take the result and put in the variables we have declared
532
  // Status is in the first element of the array so skip that.
533
  partNumber = rsp[1];
534
  fwMajor  = (char)rsp[2];
535
  fwMinor  = (char)rsp[3];
536
  patchID  = (u16)(rsp[4] << 8) | (u16)rsp[5];
537
  cmpMajor = (char)rsp[6];
538
  cmpMinor = (char)rsp[7];
539
  chipRev  = (char)rsp[8];
540
   
541
542
}

Als Ergebnis bekomme ich für fwMajor, fwMinor, usw. 0xff.


Ich vertraue auf euer Fachwissen und würde mich über Hilfe freuen.

Thomas

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.