Hallo Leute, Ich hab MPLAB mit CCS Compiler (MPLAB Version 5). Ich kann MPLAB leider nicht updaten, da das aktuelle MPLAB Version 8 den alten ICD-Programmer/Debugger für die 16F8xx Serie nicht mehr kann. Da hab ich das Problem, dass der Code bei "i2c_start();" hängen bleibt! Egal ob ich den ICD-Debugger verwende oder nicht. Hatte jemand von euch einen solchen Fehler schon mal? gruss Michael
Hallo, ich habe daselbe Problem. das ist mein Code:
1 | void IdleI2C( void ) |
2 | {
|
3 | while ( ( SSPCON2 & 0x1F ) )continue; |
4 | }
|
5 | |
6 | void StartI2C( void ) |
7 | {
|
8 | SSPCON2bits.SEN = 1; // initiate bus start condition |
9 | while(SSPCON2bits.SEN); |
10 | }
|
11 | u08 WriteI2C( u08 data_out ) |
12 | {
|
13 | SSPBUF = data_out; // write single byte to SSPBUF |
14 | if ( SSPCON1bits.WCOL ) // test if write collision occurred |
15 | return ( -1 ); // if WCOL bit is set return negative # |
16 | else
|
17 | {
|
18 | while( SSPSTATbits.BF ); // wait until write cycle is complete |
19 | return ( 0 ); // if WCOL bit is not set return non-negative # |
20 | }
|
21 | }
|
22 | void StopI2C( void ) |
23 | {
|
24 | SSPCON2bits.PEN = 1; // initiate bus stop condition |
25 | }
|
26 | u08 I2C_senden(u08 addr, u08 data) |
27 | {
|
28 | IdleI2C(); |
29 | StartI2C(); |
30 | IdleI2C(); |
31 | WriteI2C(addr&0xFE); |
32 | IdleI2C(); |
33 | if(SSPCON2bits.ACKSTAT) |
34 | {
|
35 | StopI2C(); |
36 | return 0; |
37 | }
|
38 | WriteI2C(data); |
39 | IdleI2C(); |
40 | if(SSPCON2bits.ACKSTAT) |
41 | {
|
42 | StopI2C(); |
43 | return 0; |
44 | }
|
45 | StopI2C(); |
46 | return 1; |
47 | }
|
48 | |
49 | u08 I2C_lesen(void) |
50 | {
|
51 | SSPCON2bits.RCEN = 1; // enable master for 1 byte reception |
52 | while (!SSPSTATbits.BF ); // wait until byte received |
53 | return ( SSPBUF ); // return with read byte |
54 | }
|
55 | |
56 | |
57 | |
58 | u08 DataRdyI2C( void ) |
59 | {
|
60 | if ( SSPSTATbits.BF ) // test if buffer full bit is set |
61 | return (1 ); // data in SSPBUF register |
62 | else
|
63 | return ( 0 ); // no data in SSPBUF register |
64 | }
|
65 | u08 recevoir(void) |
66 | {
|
67 | u08 y=0;; |
68 | if(DataRdyI2C()) |
69 | {
|
70 | y=I2C_lesen(); |
71 | if(y==0x45) |
72 | {
|
73 | LATDbits.LATD1=1; |
74 | LATDbits.LATD2=0; |
75 | }else{ |
76 | LATDbits.LATD2=1; |
77 | LATDbits.LATD1=0; |
78 | }
|
79 | }
|
80 | }
|
wenn du eine Antwort hat kannst du mir helfen
Ich hab das Hardware-I2C Modul des PIC 16F877 verwendet. Mein Code sieht so aus:
1 | #include <16f877.h> |
2 | #device ICD=TRUE
|
3 | #use delay(clock=20000000)
|
4 | #include <lcd.c> |
5 | #use i2c(master, sda=PIN_C4, scl=PIN_C3, noforce_sw)
|
6 | |
7 | int i2cT1,i2cT2; |
8 | |
9 | main() |
10 | {
|
11 | lcd_init(); |
12 | |
13 | i2c_stop(); |
14 | |
15 | while(TRUE) |
16 | {
|
17 | i2c_start(); |
18 | i2c_write(0b10010001); |
19 | i2cT1=i2c_read(); |
20 | i2cT2=i2c_read(0); |
21 | i2c_stop(); |
22 | |
23 | |
24 | delay_ms(50); |
25 | |
26 | lcd_gotoxy(1,1); |
27 | printf(lcd_putc,"1:%3u",i2cT1); |
28 | lcd_gotoxy(1,2); |
29 | printf(lcd_putc,"2:%3u",i2cT2); |
30 | |
31 | delay_ms(500); |
32 | }
|
33 | |
34 | }
|
Bei diesem Code bleibt der Microcontroller immer beim Befehl "i2c_start();" hängen. Sieht man im ICD Debugger schön! Was kann hier der Grund sein? Ich hab schon nachgesehen, scl und sda Pin's sind mit Pullup auf +5V gelegt. Der LM75 Temperatursensor, welcher am I2C Bus hängt hat addresse "000" und ich möchte aus diesem Lesen. Hatte jemand sochon mal sowas? Michael
Bei einem Fujitsu Controller hatte ich mal ein ähnliches Problem, der Controller blieb blieb hängen, weil die SDA Leitung nicht erwartungsgemäß auf High ging. Und das war so: Es wurde ein I2C EEPROM ausgelesen, bei dem viele Datenzellen auf "0" waren. Erwartungsgemäß ist somit beim Auslesen die SDA Leitung relativ häufig Low. Sporadisch hing sich das Protokoll auf, auch nach kompletten Neustart ging nichts. Es klemmte ebenfalls bei der Erzeugung der Start-Condition. Nach längeren Arbeitspausen (ab ca. 20 Minuten) ging es dann auf einmal wieder. Auffällig war bei Messungen auf jeden Fall, dass das EEPROM seinerseits die Datenleitung auf Low zog. Einfach so, auch nach Reset und Trennung der Spannung. Warum? Es handelte sich um ein EEPROM, dass auch noch für Spannungen ab 1.8V spezifiziert war. Ein EEPROM hat keinen Reset-Eingang, die interne State-Machine wird nur bei einem Power-On Reset zurückgesetzt. Irgendwann hat es eine Verhakung im Protokoll gegeben und das EEPROM ist auf SDA=0 stehengeblieben. Das Ausschalten der Spannung hat nichts gebracht, da VCC relativ lange bei ca. 1V stehenbleibt. Das EEPROM war selbst bei dieser Spannung noch funktionell. Erst nach langer Zeit fällt die Spannung weit unter 1V und das EEPROM machte einen vernünftigen Power-On Reset. Daher das Phänomen nach Mittagspause, wo kurzzeitig wieder alles funktionierte. Die Lösung lag darin, nach Power-On des Mikrocontrollers einfach einige zig Takte auf SCL manuell zu erzeugen, während SDA=1 bleibt. Dadurch kam die State-Machine im EEPROM wieder in den Tritt und der I2C Controller im Mikrocontroller fand bei Erzeugung der Start-Bedingung den korrekten Zustand SDA=1 vor! Dieses Phänomen könntet ihr auch mal abchecken, die I2C Start Implementierungen bei verschiedenen Controllern sind häufig so gestrickt, dass einfach per Endlos-Loop auf SDA=1 (Busfreigabe) gewartet wird. Ist bei dieser Abfrage definitiv SDA=1 ???
Hallo Danke für die Hilfe! Ich hab's jetzt mit der Software-Variante des CCS Compilers geschafft! Es gibt hier zwei Möglichkeiten: einmal um das integrierte i2c Modul zu verwenden
1 | #use i2c(master, sda=PIN_C4, scl=PIN_C3, noforce_sw)
|
oder
1 | #use i2c(master, sda=PIN_C4, scl=PIN_C3)
|
Mit der 2ten Variante ohne Hardware Modul läuft es ohne Probleme! Um auf die software Implementierung zurückzugreifen. Offensichtlich hat mein LM75 hier ein Problem damit. Ich werde mal den Tipp mit den SCL Takten versuchen! danke Michael
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.