hallo! ich versuche gerade ein kleines C programm zu schreiben das mir ein paar bytes von der seriellen schnittstelle einliest! das einlesen funktioniert auch eigentlich nur mein problem ist hauptsächlich das es in c keinen byte datentyp gibt und ich somit chars verwenden muss. ich habe mein programm so eingestellt das es alle 100ms einen wert schickt der immer erhöht wird also von 0 bis 255 und dann wieder von vorne anfängt, um alle zahlen zu testen. wenn ich die daten nun wegschicke empfange ich diese Werte! 1 2 253 253 252 5 6 7 8 9 0 246 11 12 0 243 14 15 16 239 238 237 20 235 234 233 24 25 230 27 228 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 129 128 0 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 0 229 0 231 232 0 0 236 237 238 239 240 241 242 243 0 244 245 246 0 247 248 249 250 251 0 0 0 254 1 2 253 253 252 5 6 7 8 9 0 246 11 12 0 243 14 15 16 239 238 237 20 235 234 233 24 25 230 27 228 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 man sieht sofort das ein großteil der werte stimmen, jedoch gerade bei sonderzeichen in der ASCII tabelle wie LF NL oder DEL liest er einen falschen zahlenwert ein! in meinem fall 0 oder irgendeinen zu hohen Wert! jetzt wäre es halt interessant wie man so einen fehler wegbekommen könnte da ich ja im idealfall gerne Messwerte im bereich von einem byte übertragen würd!
Etwas dünne Infos zu eingestellten Parametern und zur verwendeten Hardware, Programmcode sowieso. Mein Tipp: Die Übertragungsrate ist beim Sender und/oder Empfänger abweichend vom Sollwert. Die Abweichung ist so gering, dass noch kein Hardwarefehler ausgelöst wird und so hoch, dass bereits einige Bits unsauber empfangen werden und die Bytes daraus verstümmelt werden.
also die baudrate müsste eigentlich auf beiden seiten richtig eingestellt sein! ebenfalls Stop/Parity bit! hier noch mein c code!
1 | int configserial(int fd, int baud) |
2 | {
|
3 | struct termios options; |
4 | /* Get the current options for the port...*/
|
5 | tcgetattr(fd, &options); |
6 | /* Set the baud rates to 19200...*/
|
7 | cfsetispeed(&options, translatebaud(baud)); |
8 | cfsetospeed(&options, translatebaud(baud)); |
9 | /* Enable the receiver and set local mode...*/
|
10 | options.c_cflag |= (CLOCAL | CREAD); |
11 | |
12 | options.c_cflag &= ~PARENB; |
13 | options.c_cflag &= ~CSTOPB; |
14 | options.c_cflag &= ~CSIZE; |
15 | options.c_cflag |= CS8; |
16 | |
17 | /* Set the new options for the port...*/
|
18 | tcsetattr(fd, TCSANOW, &options); |
19 | return 1; |
20 | }
|
21 | |
22 | |
23 | int writeport(int fd, char *chars) { |
24 | int n; |
25 | |
26 | int len = strlen(chars); |
27 | chars[len] = 0x0d; /* stick a <CR> after the command*/ |
28 | chars[len+1] = 0x00; /* terminate the string properly*/ |
29 | n = write(fd, chars, strlen(chars)); |
30 | if (n < 0) { |
31 | fputs("write failed!\n", stderr); |
32 | return 0; |
33 | }
|
34 | return 1; |
35 | }
|
36 | |
37 | |
38 | int main(int args, char *argv[]) |
39 | {
|
40 | fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY | O_NDELAY); |
41 | if (fd == -1) { |
42 | BailOut("SERIAL: open_port: Unable to open Serial device!"); |
43 | } else { |
44 | fcntl(fd, F_SETFL, 0); |
45 | }
|
46 | |
47 | fprintf(stderr,"baud=%d", getbaud(fd)); |
48 | configserial(fd,BAUDRATE); |
49 | fprintf(stderr,"baud=%d", getbaud(fd)); |
50 | |
51 | fcntl(fd, F_SETFL, O_SYNC ); |
52 | |
53 | /* endless read serial */
|
54 | while(TRUE) { |
55 | if(readport(fd,rMessage)==1) |
56 | {
|
57 | fprintf(stderr,"%d ", rMessage[0]); |
58 | |
59 | /* write into filesystem */
|
60 | data.received1 = rMessage[0]; |
61 | data.received2 = rMessage[1]; |
62 | }
|
63 | }
|
64 | }
|
Was für Hardware setzt Du denn da ein? Kommunizieren da zwei PCs miteinander oder ein µC mit einem PC? In letzerem Falle: Womit erzeugst Du da die Baudrate? Was erzeugt den Takt des µC?
es kommuniziert der PC mit einem Atmega128 der hat ein 14.7Mhz Quarz drauf! UART config:
1 | # define CPU_CLK 14745600
|
2 | # define BAUDRATE_MAGIC(x) ((CPU_CLK >> 4) / x - 1)
|
3 | |
4 | # define MY_UART1_CONTROL_A UCSR1A
|
5 | # define MY_UART1_CONTROL_B UCSR1B
|
6 | # define MY_UART1_CONTROL_C UCSR1C
|
7 | |
8 | # define MY_UART1_BAUDRATE_H UBRR1H
|
9 | # define MY_UART1_BAUDRATE_L UBRR1L
|
10 | |
11 | void init_uart1(uint8_t mode, uint32_t baud, void (*receivefunction)(uint8_t data)) |
12 | {
|
13 | if(receivefunction != NULL) |
14 | receivefunctionpointer1 = receivefunction; |
15 | |
16 | MY_UART1_CONTROL_A = 0x00; //set control register A to 0x00 |
17 | MY_UART1_CONTROL_B = 0x18; //Enable receiver und transmitter |
18 | |
19 | MY_UART1_CONTROL_C |= ((1<<UCSZ11) | (1<<UCSZ10)); //8 bit, no parity, 1 stopbit |
20 | |
21 | |
22 | //set baut rate
|
23 | MY_UART1_BAUDRATE_H = (BAUDRATE_MAGIC(baud) >> 8); |
24 | MY_UART1_BAUDRATE_L = (BAUDRATE_MAGIC(baud) & 0xFF); |
25 | |
26 | //enable RX Interrupt
|
27 | MY_UART1_CONTROL_B |= (1<<RXCIE0); |
28 | }
|
29 | |
30 | uint8_t send_byte1(uint8_t byte) |
31 | {
|
32 | // Wait for empty transmit buffer
|
33 | while ( !(UCSR1A & (1<<UDRE1)) ) |
34 | ;
|
35 | // Start transmission
|
36 | MY_UART1_DATA_REGISTER = byte; |
37 | |
38 | return 0; |
39 | }
|
nachdem man das init aufgerufen hat kann man dann mit send_byte1('<zeichen>') das byte wegschicken!
Sieht AVR-seitig OK aus. Probiere mal die PC-Seite in den RAW Modus zu bringen Beitrag "serielle Schnittstelle sendet nicht mehr"
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.