Si4705 und C8051F321 kommunizieren nicht

OP #2449766
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
Angehängte Dateien:

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren