AVR - comunicación extraña entre ATmega8A y el módulo bluetooth

1

Estoy usando ATmega8A-PU microcontrolador AVR y módulo bluetooth HC-05 en una placa de pruebas.

Lo que estoy haciendo aquí es conectarse al módulo BT desde mi teléfono móvil y cambiar el estado del LED mediante el envío de comandos al microcontrolador.

Pero el problema es que, al enviar un personaje al microcontrolador a través del módulo BT, no recibiré el mismo personaje y el LED no se activará.

Conecté el módulo BT y el LED al microcontrolador mediante los siguientes esquemas:

Loquehiceaquí:

  1. VCCconectado&LospinesGNDcorrectamente.
  2. conectóelpinTXdelmóduloBTalpinRXdelmicrocontrolador.
  3. bajóelvoltajedelpinTXdelmicrocontroladorde+5va+3.3v,yloconectéalpinRXdelmóduloBT(técnicadedivisióndevoltajeV2=R2xV1/(R1+R2))yaqueestepinoperasoloen3.3v.
  4. conectóunLEDde5mmalpinPB0delmicrocontrolador.

Asíquesupongoquelapartedehardwareestáconfiguradacorrectamenteynohayningúnproblemaaquí,yaqueelmóduloBTyelLEDfuncionanperfectamente.

CompilomisprogramasenLinux,plataformaUbuntu16.04porelcompiladoravr-gcc.
TambiénutilizounprogramadorAVRUSBaspparacargararchivoshexenelmicrocontrolador.

EstablecílavelocidadenbaudiosdelmóduloBTigualaladelmicrocontrolador,paraquepuedanhablarentresíalamismafrecuencia.
LavelocidaddetransmisiónpredeterminadadeATmega8Aes9600.
LavelocidadenbaudiosdelmóduloBTes38400pordefecto,peroparaquefuncioneconelmicrocontrolador,loconfiguroen9600medianteloscomandosAT(AT+UART=9600,0,0)usandolaplataformaArduino.(Talvezestocauseelproblemaquevoyaexplicar).

Debotenerencuentaquenopuedoconfigurarlavelocidadenbaudiosdelmicrocontroladoren38400,yaqueelcompiladoradviertequelavelocidadenbaudiosesmayorquelapermitida.esporesoquecambiélavelocidadenbaudiosdelmóduloBT.

Finalmente,compiléelsiguientecódigoylosubíalmicrocontrolador:

#defineF_CPU1000000UL#defineFOSC1843200//ClockSpeed#defineBAUD9600#defineMYUBRRFOSC/16/BAUD-1#definebitset(bit)(1<<(bit))#defineis_set(sfr,port)(((sfr)&bitset((port))))#defineis_dead(sfr,port)(!is_set((sfr),(port)))#definewait_to_set(sfr,port)do{}while(is_dead((sfr),(port)))#definewait_to_die(sfr,port)do{}while(is_set((sfr),(port)))#include<avr/io.h>#include<util/setbaud.h>voidUSART_Init(constuint8_tubrr){UCSRA|=(1<<U2X);UCSRB=(1<<RXEN)|(1<<TXEN);UCSRC=(1<<URSEL)|(1<<USBS)|(3<<UCSZ0);UBRRH=(ubrr>>8);UBRRL=ubrr;}voidUSART_Flush(){unsignedchardummy;while(UCSRA&(1<<RXC))dummy+=UDR;}voidUSART_Transmit(constunsignedchardata){/*Waitforemptytransmitbuffer*/while(!(UCSRA&(1<<UDRE)));/*Putdataintobuffer,sendsthedata*/UDR=data;}uint8_tUSART_Receive(){/*Waitfordatatobereceived*/while(!(UCSRA&(1<<RXC)));/*Getandreturnreceiveddatafrombuffer*/returnUDR;}inlinevoidLED_poweron(){PORTB|=(1<<PB0);}inlinevoidLED_poweroff(){PORTB&=~(1<<PB0);}intmain(){USART_Init(MYUBRR);//setupserialconnectionDDRB=0xff;//setupLEDDDRPORTB=0;//poweroffLEDatthebeginningwhile(1){constuint8_tbyte=USART_Receive();//receivedataUSART_Flush();//flushUDRtodropuselessdataif(byte==2)LED_poweron();elseif(byte==1)LED_poweroff();USART_Transmit(byte);//senddatabacktosender}return0;}

Elcódigoessimple.
inicializalaconexiónserialyrecibedatosdelmóduloBT.silosdatoscontienenelnúmero2,elLEDseencenderá,sielnúmero1,elLEDseapagaráycualquierotrovalorseignorará,yfinalmenteelvalorsetransmitiránuevamentealremitente.

Compiloysuboestecódigoconlossiguientescomandos:

avr-gcc-Os-Wall-mmcu=atmega8a-oserial.oserial.cavr-objcopy-j.textserial.oserial.hex2>/dev/nullavrdude-pm8-cusbasp-b9600-Uflash:w:serial.hex

Elcódigosecargacorrectamenteynoapareceráningúnerror.

avrdude:warning:cannotsetsckperiod.pleasecheckforusbaspfirmwareupdate.avrdude:AVRdeviceinitializedandreadytoacceptinstructionsReading|##################################################|100%0.01savrdude:Devicesignature=0x1e9307(probablym8)avrdude:NOTE:"flash" memory has been specified, an erase cycle will be performed
        To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: reading input file "serial.hex"
avrdude: input file serial.hex auto detected as ELF
avrdude: writing flash (146 bytes):

Writing | ################################################## | 100% 0.12s

avrdude: 146 bytes of flash written
avrdude: verifying flash memory against serial.hex:
avrdude: load data flash data from input file serial.hex:
avrdude: input file serial.hex auto detected as ELF
avrdude: input file serial.hex contains 146 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.11s

avrdude: verifying ...
avrdude: 146 bytes of flash verified

avrdude: safemode: Fuses OK (E:FF, H:D9, L:E1)

avrdude done.  Thank you.

Utilizo Terminal Bluetooth Serie Android Aplicación para conectar al módulo BT desde mi teléfono.

El problema se produce justo aquí, cuando envío una cadena al módulo BT, envía de vuelta los caracteres que no son ASCII y el LED no cambia.

La parte impar es que me di cuenta de que cuando la función USART_Receive recibe 1 byte, itera 4 veces y recibe 4 bytes en su lugar.
Encontré esto configurando el LED para que parpadee cada vez que esa función recibe un byte.

Expliqué todo en detalle, ¿por qué no estoy recibiendo el mismo carácter que estoy enviando al módulo de BT?
¿Se trata del momento? ¿Tasas de baudios mal configuradas?
¡No tengo idea de lo que está pasando!

EDITAR: puede encontrar este proyecto aquí

    
pregunta Brian SP

1 respuesta

2

Surgen varios problemas obvios, pero también puede haber otros problemas

  

conectado VCC & Los pines GND correctamente.

No, no lo has hecho. A su MCU le faltan dos conexiones de alimentación requeridas por la crítica. Esto es conocido para provocar fallas interesantes. Debe conectar todos los pines de alimentación, no solo algunos de ellos.

  

si los datos contienen el número 2, el LED se encenderá, si se mantiene el número 1, el LED se apagará y cualquier otro valor se ignorará

Esto no se implementa de la forma que se esperaría en el tipo de contexto que tiene. Su código está buscando los valores de byte 1 y 2. Pero estos son códigos de control no imprimibles. Si bien es posible enviarlos a través de un enlace en serie, normalmente no son valores que se enviarían, al menos no hasta que se ingrese en un modo de limpieza binaria.

Más típicamente, en una configuración simple lo haría intercambiando representaciones de cadenas de números imprimibles. Entonces, por ejemplo, 1 tiene el código 0x31 y también se puede representar en un compilador C / C ++ como una constante de caracteres '1'

También es muy posible que cualquier cosa que use para enviar datos se intercalará con otros caracteres como retornos de carro y nuevas líneas. Si ese es el caso, su rutina de descarga puede volverse problemática: si recibe algo, la falta de sincronización significa que es bastante posible que consuma el siguiente byte que desea evaluar. Pero la forma en que asume que el siguiente indicador de caracteres estará presente de inmediato, en comparación con la velocidad del procesador que sea lo suficientemente rápida como para "ver" fácilmente el tiempo que tarda un byte en llegar, sugiere que es probable que no reciba nada.

Es probable que desee evaluar todos los bytes recibidos. Si los valores son contextuales, debe hacer un seguimiento de su contexto en una máquina de estado, no simplemente por cuestión de tiempo, especialmente porque la naturaleza empaquetada del bluetooth puede agrupar los bytes de forma extraña en el tiempo, ya sea ejecutando juntos las cosas que se enviaron con leves retrasos, o introduciendo retrasos entre bytes que fueron inmediatamente secuenciales en la entrada original.

Es muy posible que su ATmega no esté funcionando a la velocidad en baudios que espera. Por ejemplo, aún puede tener habilitada la división de reloj predeterminada por la configuración de fusibles predeterminada. O puede estar operando con el oscilador interno, no con el cristal externo que ha proporcionado, nuevamente debido a los fusibles predeterminados. Hacer un programa alternativo rápido que imprima un carácter una y otra vez, y verificar que su PC pueda recibirlo sería una buena prueba; mejor aún, compruebe la tasa de salida con un osciloscopio.

Puede verificar dos veces la configuración de la velocidad en baudios del módulo operando el sistema Arduino alternativo a 9600 baudios. También puede trabajar a través de los cálculos de división y ver cuál será el error en la configuración de 9600 baudios para su frecuencia de cristal atípica. Además, debería dedicar tiempo a comprender las dos posibles configuraciones de sobremuestreo. Puede ser interesante saber que puede volver a leer la configuración del divisor en un Arduino después de que el UART esté configurado por las bibliotecas habituales, aunque, por supuesto, esto estará en el contexto de la frecuencia de reloj del Arduino. También puede cambiar la configuración del reloj en su programa básico para que coincida con el reloj de Arduino e intentarlo en el Arduino (solo asegúrese de cargar el programa resultante a través del cargador de arranque; si usted ISP, su Arduino borrará su cargador de arranque y tendrá para usar el ISP para restaurar eso).

Otra cosa que podría hacer para la depuración sería conectar una entrada serial de nivel lógico de su PC a la salida del módulo BT en paralelo con el ATmega. Luego, puede usar un programa en serie en su PC (idealmente uno que pueda mostrar los valores reales de bytes como un volcado hexadecimal) para ver qué es lo que el módulo BT está realmente emitiendo, en todo caso. En este momento, su proyecto tiene muchas partes móviles y usted tiene muy poca visibilidad de cuál de ellas no está funcionando de la manera que esperaba.

    
respondido por el Chris Stratton

Lea otras preguntas en las etiquetas