Microcontroladores Atmega8. Programación Atmega8 para principiantes. Microcontroladores AVR. Programación para principiantes Entrenamiento de microcontrolador atmega8

diciembre 2015

1. Ventajas del método propuesto

Los circuitos de dispositivos basados ​​en microcontroladores (MCU) suelen caracterizarse por una combinación de dos cualidades difíciles de combinar: máxima simplicidad y alta funcionalidad. Además, la funcionalidad se puede cambiar y ampliar en el futuro sin realizar ningún cambio en el circuito, simplemente reemplazando el programa (parpadeando). Estas características se explican por el hecho de que los creadores de los MK modernos intentaron colocar en un chip todo lo que un desarrollador podría necesitar. dispositivo electronico- al menos tanto como sea posible. Como resultado, hubo un cambio de énfasis de los circuitos y la instalación al software. Con el uso de MK, ahora hay menos necesidad de "cargar" el circuito con piezas y hay menos conexiones entre componentes. Esto, por supuesto, hace que el circuito sea más atractivo para que lo repitan tanto los ingenieros electrónicos experimentados como los novatos. Pero, como siempre, hay que pagar por todo. Esto tampoco estuvo exento de dificultades. Si compra un MK nuevo, lo instala en un circuito correctamente ensamblado a partir de piezas reparables y le aplica energía, nada funcionará: el dispositivo no funcionará. El microcontrolador necesita un programa.

Parecería que con esto también todo es simple: en Internet puede encontrar muchos esquemas con firmware gratuito. Pero aquí hay un problema: el firmware debe "cargarse" de alguna manera en el microcontrolador. Para alguien que nunca ha hecho esto antes, esta tarea a menudo se convierte en un problema y en el principal factor repulsivo, lo que a menudo lo obliga a abandonar el placer de usar MK y buscar esquemas basados ​​en una lógica "flexible" y rígida. Pero no todo es tan complicado como podría parecer a primera vista.

Después de analizar las publicaciones en Internet, se puede ver que este problema se resuelve con mayor frecuencia de dos maneras: comprando un programador ya hecho o fabricando uno casero. Al mismo tiempo, los circuitos publicados por programadores caseros suelen ser excesivamente complejos, mucho más complejos de lo realmente necesario. Por supuesto, si planeas flashear el MK todos los días, es mejor tener un programador "genial". Pero si la necesidad de tal procedimiento surge con poca frecuencia, de vez en cuando, entonces puede prescindir por completo de un programador. No, por supuesto, no estamos hablando de aprender a hacer esto con el poder del pensamiento. Esto significa que al comprender cómo interactúa el programador con el microcontrolador cuando escribe y lee información en su modo de programación, podemos arreglárnoslas con las herramientas disponibles para un propósito más amplio. Estas herramientas deberán reemplazar tanto las partes de software como de hardware del programador. El hardware debe proporcionar una conexión física al microcircuito MK, la capacidad de aplicar niveles lógicos a sus entradas y leer datos de sus salidas. La parte del software debe asegurar el funcionamiento del algoritmo que controla todos los procesos necesarios. También observamos que la calidad de la grabación de información en el MK no depende de qué tan "genial" sea su programador. No existe “mejor grabado” o “peor”. Sólo hay dos opciones: “registrado” y “no registrado”. Esto se explica por el hecho de que el proceso de grabación dentro del cristal está controlado directamente por el propio MK. Solo necesita proporcionarle energía de alta calidad (sin interferencias ni ondulaciones) y organizar adecuadamente la interfaz. Si los resultados de la lectura de prueba no revelan errores, entonces todo está en orden: puede usar el controlador para el propósito previsto.

Para escribir un programa en el MK sin tener un programador, necesitamos un conversor de puerto USB-RS232TTL y también. El convertidor USB-RS232TTL le permite utilizar un puerto USB para crear un puerto COM que se diferencia del "real" solo en que sus entradas y salidas utilizan niveles lógicos TTL, es decir, voltaje en el rango de 0 a 5 voltios ( puedes leer más en el artículo " "). En cualquier caso, es útil tener un convertidor de este tipo en su “hogar”, por lo que si aún no tiene uno, definitivamente vale la pena comprarlo. En cuanto a los niveles lógicos, en nuestro caso TTL es incluso una ventaja sobre un puerto COM normal, porque las entradas y salidas de dicho puerto se pueden conectar directamente a cualquier microcontrolador alimentado por 5 V, incluidos ATtiny y ATmega. Pero no intente utilizar un puerto COM normal: utilizan voltajes en el rango de -12 a +12 V (o -15...+15 V). En este caso, ¡¡¡la conexión directa al microcontrolador es inaceptable!!!

La idea de crear un script para el programa Perpetuum M, que implementa las funciones del programador, surgió después de leer en Internet una serie de publicaciones que ofrecen determinadas soluciones para el firmware MK. En cada caso se descubrieron graves deficiencias o dificultades excesivas. A menudo me encontraba con circuitos de programación que contenían un microcontrolador y, al mismo tiempo, me daban consejos bastante serios como: "... y para programar el microcontrolador para este programador necesitaremos... así es, ¡otro programador!" A continuación, se sugirió ir con un amigo y buscar servicio pagado etcétera. La calidad del software distribuido en la red para estos fines tampoco fue impresionante: se notaron muchos problemas tanto con la funcionalidad como con la "nubosidad" de la interfaz de usuario. A menudo se necesita mucho tiempo para comprender cómo utilizar un programa; es necesario estudiarlo incluso para realizar las acciones más simples. Otro programa puede hacer algo durante mucho tiempo y con diligencia, pero el usuario se entera de que no se escribe nada en el MK solo después de que todo el firmware se haya completado por completo y la posterior lectura de prueba. También ocurre el siguiente problema: el usuario intenta seleccionar su MK de la lista de cristales compatibles, pero no está en la lista. En este caso, no podrá utilizar el programa; por regla general, no se proporciona la inclusión en la lista de MK faltantes. Además, seleccionar manualmente un controlador de la lista parece extraño, considerando que en muchos casos el programador puede determinar por sí mismo el tipo de MK. Todo esto no se dice para arrojar barro a los productos existentes, sino para explicar el motivo de la aparición del script del programa Perpetuum M, descrito en este artículo. El problema realmente existe y afecta principalmente a los principiantes que no siempre logran superar este "muro" para dar el primer paso en el mundo de los microcontroladores. El guión propuesto tiene en cuenta las deficiencias encontradas en otros programas. Se ha implementado la máxima “transparencia” del funcionamiento del algoritmo, una interfaz de usuario extremadamente sencilla que no requiere aprendizaje y no deja ninguna posibilidad de confundirse y “hacer clic en algo equivocado”. Si el MK requerido no se encuentra entre los compatibles, puede agregar su descripción usted mismo, tomando los datos necesarios de la documentación descargada del sitio web del desarrollador de MK. Y, lo más importante, el guión está abierto a estudio y modificación. Cualquiera puede, abriendo en editor de texto, estúdialo y edítalo a tu propio criterio, cambiando las funciones existentes a tu gusto y agregando las que faltan.

La primera versión del guión se creó en junio de 2015. Esta versión solo brinda soporte para los microcontroladores de las series ATtiny y ATmega de Atmel con funciones para escribir/leer memoria flash, establecer bits de configuración y detectar automáticamente el tipo de controlador. La escritura y lectura de EEPROM no está implementada. Había planes para complementar la funcionalidad del script. : agregar escritura y lectura de EEPROM, implementar soporte para controladores PIC, etc. Por esta razón el script aún no se ha publicado, pero por falta de tiempo se retrasó la implementación del plan, para que no llegue lo mejor enemigo de lo bueno, se decidió publicar la versión existente. Si las funciones ya implementadas no son suficientes, no se enoje. En este caso, puede intentar agregar la función deseada usted mismo. No lo ocultaré: La idea de crear este script inicialmente también tiene un significado educativo. Habiendo entendido el algoritmo y agregando algo propio, podrá comprender mejor el funcionamiento del MK en modo de programación, de modo que en En el futuro no te encontrarás en la posición de una chica frente a un coche averiado, mirando pensativamente su interior y sin entender por qué “no funciona”.

2. Interfaz MK en modo de programación

Hay varias formas diferentes de poner el controlador en modo de programación y trabajar con él en este modo. El más fácil de implementar para los controladores de las series ATtiny y ATmega es quizás SPI. Lo usaremos.

Pero antes de comenzar a considerar las señales necesarias para generar SPI, haremos una serie de reservas. El microcontrolador tiene bits de configuración. Se trata de algo así como interruptores de palanca, cuya conmutación permite cambiar algunas propiedades del microcircuito de acuerdo con las necesidades del proyecto. Físicamente, se trata de células de memoria no volátiles, como aquellas en las que se escribe un programa. La diferencia es que hay muy pocos (hasta tres bytes para ATmega) y no forman parte del espacio de direcciones de ninguna memoria. La escritura y lectura de datos de configuración se realiza mediante comandos separados en el modo de programación MK. Ahora es importante tener en cuenta que algunos bits de configuración afectan la capacidad misma de usar SPI. Con algunos de sus valores, puede resultar que no se pueda utilizar SPI. Si se encuentra con un microcontrolador de este tipo, el método propuesto en este artículo no le ayudará. En este caso, tendrá que cambiar la configuración de los bits de configuración en el programador, que admite un modo de programación diferente, o utilizar un microcontrolador diferente. Pero este problema sólo se aplica a los MK usados, o aquellos con los que alguien ya ha "jugueteado" sin éxito. El hecho es que las nuevas MCU vienen con ajustes de bits de configuración que no impiden el uso de SPI. Esto lo confirman los resultados de la prueba del script del programador del programa Perpetuum M, durante el cual se actualizaron con éxito cuatro MK diferentes (ATmega8, ATmega128, ATtiny13, ATtiny44). Todos eran nuevos. La configuración inicial de los bits de configuración fue consistente con la documentación y no interfirió con el uso de SPI.

Teniendo en cuenta lo anterior, debes prestar atención a los siguientes bits. El bit SPIEN permite o deshabilita explícitamente el uso de SPI, por lo tanto en nuestro caso su valor debe ser habilitante. El bit RSTDISBL es capaz de convertir una de las salidas del microcircuito (predeterminada) en la entrada de la señal de "reset", o no convertirla (dependiendo del valor escrito en este bit). En nuestro caso, la entrada “reset” es necesaria (si no está presente, no será posible cambiar el MK al modo de programación vía SPI). También hay bits del grupo CKSEL que especifican la fuente de la señal de reloj. No impiden el uso de SPI, pero también deben tenerse en cuenta, porque si no hay ningún pulso de reloj, o si su frecuencia es inferior a la aceptable para una velocidad SPI determinada, tampoco sucederá nada bueno. Normalmente, las nuevas MCU que tienen un oscilador RC interno tienen los bits del grupo CKSEL configurados para usarlo. Esto nos conviene bastante: el fichaje se realiza sin ningún esfuerzo adicional por nuestra parte. No es necesario soldar el resonador de cuarzo ni conectar un generador externo. Si los bits especificados contienen una configuración diferente, deberá encargarse de sincronizar el reloj de acuerdo con la configuración. En este caso, puede que sea necesario conectar un resonador de cuarzo o un generador de reloj externo a la MCU. Pero en este artículo no consideraremos cómo se hace esto. Los ejemplos de conexión de un MK para programación contenidos en este artículo están diseñados para el caso más simple.

Arroz. 1. Intercambio de datos vía SPI en modo programación

Ahora pasemos a la Figura 1, extraída de la documentación del ATmega128A MK. Muestra el proceso de transmitir un byte al MK y recibir simultáneamente un byte del MK. Ambos procesos, como vemos, utilizan los mismos pulsos de reloj suministrados desde el programador al microcontrolador en su entrada SCK, uno de los pines del microcircuito, al que se le asigna esa función en el modo de programación SPI. Dos líneas de señal más proporcionan recepción y transmisión de datos un bit por ciclo de reloj. A través de la entrada MOSI, los datos ingresan al microcontrolador y los datos leídos se toman de la salida MISO. Observe las dos líneas de puntos dibujadas desde SCK a MISO y MOSI. Muestran en qué momento el microcontrolador "se traga" el bit de datos establecido en la entrada MOSI y en qué momento él mismo establece su propio bit de datos en la salida MISO. Todo es bastante sencillo. Pero para ingresar el MK al modo de programación, todavía necesitamos una señal de RESET. Tampoco nos olvidemos del cable GND común y de la fuente de alimentación VCC. En total, resulta que solo es necesario conectar 6 cables al microcontrolador para actualizar su firmware a través de SPI. A continuación analizaremos esto con más detalle, pero por ahora agregaremos que el intercambio de datos con el MK en modo programación vía SPI se realiza en paquetes de 4 bytes. El primer byte de cada paquete está básicamente dedicado en su totalidad a la codificación de instrucciones. El segundo byte, dependiendo del primero, puede ser una continuación del código de comando, o parte de la dirección, o puede tener un valor arbitrario. El tercer byte se utiliza principalmente para transmitir direcciones, pero puede tener un valor arbitrario en muchas instrucciones. El cuarto byte suele transmitir datos o tiene un valor arbitrario. Simultáneamente con la transmisión del cuarto byte, algunos comandos reciben datos provenientes del microcontrolador. Los detalles de cada comando se pueden encontrar en la documentación del controlador en la tabla denominada "Conjunto de instrucciones de programación en serie SPI". Por ahora solo observamos que todo el intercambio con el controlador se construye a partir de una secuencia de paquetes de 32 bits, en cada uno de los cuales no se transmite más de un byte de información útil. Esto no es muy óptimo, pero en general funciona bien.

3. Conexión del MK para programación

Para garantizar que se suministren todas las señales necesarias a las entradas del microcontrolador para organizar la interfaz SPI y leer datos de su salida MISO, no es necesario crear un programador. Esto se puede hacer fácilmente utilizando el convertidor USB-RS232TTL más común.

En Internet a menudo se puede encontrar información de que estos convertidores son inferiores y que no se puede hacer nada serio con ellos. Pero con respecto a la mayoría de los modelos de convertidores, esta opinión es errónea. Sí, hay convertidores a la venta que no tienen todas las entradas y salidas disponibles en comparación con un puerto COM estándar (por ejemplo, solo TXD y RXD), pero tienen un diseño no separable (el microcircuito está lleno de plástico, es imposible alcanzar sus pines). Pero no vale la pena comprarlos. En algunos casos, puede obtener las entradas y salidas de los puertos que faltan soldando el cableado directamente al chip. En la Figura 2 se muestra un ejemplo de un convertidor "mejorado" (chip PL-2303; más detalles sobre el propósito de sus pines en el artículo ""). Este es uno de los modelos más baratos, pero tiene sus propias ventajas cuando se utiliza en diseños caseros. También están muy extendidos los cables adaptadores con todas las funciones con un conector estándar de nueve pines en el extremo, como un puerto COM. Se diferencian de un puerto COM normal solo en los niveles TTL y en la incompatibilidad con los heredados. software y algunos equipos viejos. También se puede observar que los cables del chip CH34x se muestran mucho más confiables y estables en varias pruebas extremas en comparación con los convertidores del PL-2303. Sin embargo, durante el uso normal la diferencia no se nota.

Al elegir un convertidor USB-RS232TTL, también debes prestar atención a la compatibilidad de su controlador con la versión del sistema operativo que estás utilizando.

Echemos un vistazo más de cerca al principio de conectar un microcontrolador y un convertidor USB-RS232TTL usando el ejemplo de cuatro diferentes modelos MK: ATtiny13, ATtiny44, ATmega8 y ATmega128. La figura 3 muestra el diagrama general de dicha conexión. Puede que le sorprenda saber que las señales RS232 (RTS, TXD, DTR y CTS) se están utilizando de forma inadecuada. Pero no se preocupe: el programa Perpetuum M puede trabajar con ellos directamente: establecer valores de salida y leer estados de entrada. En cualquier caso, los convertidores USB-RS232TTL ampliamente utilizados en chips CH34x y PL-2303 proporcionan esta capacidad; esto se ha verificado. Tampoco debería haber problemas con otros convertidores populares, ya que se utilizan funciones estándar de Windows para acceder al puerto.

Las resistencias que se muestran en el diagrama general, en principio, no se pueden instalar, pero es mejor instalarlas. ¿Cuál es su propósito? Utilizando las entradas y salidas TTL del convertidor y la fuente de alimentación de cinco voltios del microcontrolador, nos libramos de la necesidad de coordinar niveles lógicos: todo ya es bastante correcto. Esto significa que las conexiones pueden ser directas. Pero durante los experimentos , puede pasar cualquier cosa. Por ejemplo, según la ley de la mezquindad, un destornillador puede caer justo en el lugar donde no podría caer, y cortocircuitar algo que en ningún caso debe cortocircuitarse. Por supuesto, cualquier cosa puede resulta ser un "destornillador". Las resistencias en este caso a veces reducen las consecuencias. Uno de sus propósitos es eliminar un posible conflicto de salida. El hecho es que una vez completada la programación, el microcontrolador entra en modo de funcionamiento normal y puede Sucede que su pin conectado a la salida del convertidor (RTS, TXD o DTR) también se convierte en salida, según el programa recién grabado en el MK. En este caso, sería muy malo si dos salidas conectadas directamente “pelearan” - intenta establecer diferentes niveles lógicos. En tal “lucha”, alguien puede “perder”, pero no queremos eso.

Los valores de las tres resistencias se seleccionan en el nivel de 4,3 KOhm. Esto se aplica a las conexiones entre la salida del convertidor y la entrada del microcontrolador. La precisión de las resistencias no importa: puede reducir su resistencia a 1 KOhm o aumentarla a 10 KOhm (pero en el segundo caso, el riesgo de interferencia aumenta cuando se utilizan cables largos en el camino hacia el MK). En cuanto a la conexión entre la entrada del convertidor (CTS) y la salida del microcontrolador (MISO), aquí se utiliza una resistencia de 100 ohmios. Esto se explica por las peculiaridades de la entrada del convertidor utilizado. Durante las pruebas, se utilizó un convertidor en el microcircuito PL-2303, cuyas entradas, aparentemente, están conectadas al positivo de la fuente de alimentación con una resistencia relativamente baja (del orden de varios cientos de ohmios). Para “romper el pull-up” tuve que instalar una resistencia con una resistencia tan pequeña. Sin embargo, no es necesario instalarlo en absoluto. En el convertidor esta es siempre la entrada. No puede convertirse en una salida, lo que significa que no habrá conflicto de salidas en ningún desarrollo de los acontecimientos.

Si el chip tiene un pin AVCC separado para alimentar el convertidor analógico a digital (por ejemplo, ATmega8 o ATmega128), debe conectarse al pin de alimentación VCC común. Algunos circuitos integrados tienen más de un pin de alimentación VCC o más de un GND. Por ejemplo, ATmega128 tiene 3 pines GND y 2 pines VCC. En un diseño permanente, es mejor conectar pines del mismo nombre entre sí. En nuestro caso, durante la programación, puedes usar un pin VCC y GND cada uno.

Y así es como se ve la conexión ATtiny13. La figura muestra las asignaciones de pines utilizadas al programar a través de SPI. Al lado de la foto se muestra cómo se ve en realidad una conexión temporal.


Algunos pueden decir que esto no es nada grave: conexiones en el cableado. Pero tú y yo somos personas sensatas. Nuestro objetivo es programar el microcontrolador, dedicando un mínimo de tiempo y otros recursos a ello, y no presumir delante de alguien. La calidad no sufre. El método "sobre cables" en este caso es bastante eficaz y está justificado. Actualizar el firmware del controlador es un procedimiento único, por lo que no tiene sentido cubrirlo con pedrería. Si se pretende cambiar el firmware en el futuro sin retirar el controlador del circuito (en el producto terminado), esto se tiene en cuenta durante la instalación durante la fabricación del dispositivo. Por lo general, se instala un conector (RESET, SCK, MOSI, MISO, GND) para este propósito y el MK se puede flashear incluso después de instalarlo en la placa. Pero estos son placeres creativos. Estamos considerando el caso más simple.

Ahora pasemos al ATtiny44 MK. Aquí todo es más o menos igual. Según el dibujo y la fotografía, incluso un principiante no tendrá ninguna dificultad para descubrir la conexión. Al igual que el ATtiny44, puede conectar los microcontroladores ATtiny24 y ATtiny84; las asignaciones de pines para estos tres son las mismas.


Otro ejemplo de conexión temporal de un controlador para programarlo es ATmega8. Hay más pines aquí, pero el principio es el mismo: algunos cables, y ahora el controlador está listo para "llenar" información en ellos. El cable negro extra de la foto procedente del pin 13 no participa en la programación. Está diseñado para eliminar una señal de sonido después de que el MK sale del modo de programación. Esto se debe al hecho de que mientras se depuraba el script de "Perpetuum M", el programa se descargó en el MK. Caja de música.


A menudo, un controlador está disponible en diferentes carcasas. En este caso, la asignación de pines para cada caso se distribuye de forma diferente. Si la carcasa de su controlador no es similar a la que se muestra en la figura, verifique el propósito de los pines en la documentación técnica, que puede descargarse del sitio web del desarrollador de MK.

Para completar la imagen, veamos cómo conectar un microcircuito MK con una gran cantidad de "patas". El propósito del cable negro extra en la foto proveniente del pin 15 es exactamente el mismo que en el caso del ATmega8.


Probablemente ya estés convencido de que todo es bastante sencillo. Cualquiera que sepa contar los pines de los microcircuitos (a partir de la marca en un círculo en el sentido contrario a las agujas del reloj) lo descubrirá. Y no te olvides de la precisión. Los microcircuitos aman a las personas ordenadas y no perdonan el trato descuidado.

Antes de pasar a la parte del software, asegúrese de que el controlador del convertidor USB-RS232TTL esté instalado correctamente (consulte el Administrador de dispositivos de Windows). Recuerda o anota el número del puerto COM virtual que aparece al conectar el conversor. Este número deberá ingresarse en el texto del script, sobre el cual puede leer a continuación.

4. Script - programador de "Perpetuum M"

Descubrimos la parte de hardware del "programador". Esto ya es la mitad de la batalla. Ahora queda por abordar la parte del software. Su función la desempeñará el programa Perpetuum M bajo el control de un script, que implementa todas las funciones necesarias para interactuar con el microcontrolador.

El archivo con el script debe descomprimirse en la misma carpeta donde se encuentra el programa perpetuum.exe. En este caso, cuando ejecute el archivo perpetuum.exe, se mostrará un menú en la pantalla con una lista de scripts instalados, entre los que estará la línea “Programador AVR MK” (puede que sea la única). Esta es la línea que necesitamos.

El script se encuentra en la carpeta PMS en el archivo "MK Programmer AVR.pms". Este archivo se puede ver, estudiar y editar si es necesario en un editor de texto normal como el Bloc de notas de Windows. Antes de utilizar el script, lo más probable es que necesite realizar cambios en el texto relacionado con la configuración del puerto. Para hacer esto, verifique el nombre del puerto utilizado en el Administrador de dispositivos de Windows y, si es necesario, realice la modificación apropiada en la línea "PortName="COM4";" - en lugar del número 4 puede haber otro número. Además, cuando utilice un modelo de convertidor USB-RS232TTL diferente, es posible que deba cambiar la configuración de inversión de señal (líneas de script que comienzan con la palabra "Alto"). Puedes comprobar la inversión de señales mediante el conversor USB-RS232TTL utilizando uno de los ejemplos contenidos en las instrucciones del programa Perpetuum M (apartado de funciones para trabajar con el puerto).

La subcarpeta MK_AVR contiene archivos con descripciones de controladores compatibles. Si el controlador que necesita no está entre ellos, puede agregar el que necesita usted mismo, siguiendo una analogía. Tome uno de los archivos como muestra y, utilizando un editor de texto, ingrese los datos necesarios, tomándolos de la documentación de su microcontrolador. Lo principal es tener cuidado, ingresar los datos sin errores, de lo contrario el MK no se programará o se programará incorrectamente. La versión original admite 6 microcontroladores: ATtiny13, ATtiny24, ATtiny44, ATtiny84, ATmega8 y ATmega128. El script implementa el reconocimiento automático del controlador conectado; no es necesario especificarlo manualmente. Si el identificador leído en el MK no se encuentra entre las descripciones disponibles, se muestra un mensaje que indica que no se pudo reconocer el controlador.

El archivo con el script también contiene información adicional. La carpeta de archivos del controlador AVR contiene una colección extensa y muy útil de archivos de definición del controlador. Estos archivos se utilizan al escribir sus propios programas para MK. Cuatro carpetas más "MusicBox_..." contienen archivos con un programa en lenguaje ensamblador y firmware listos para descargar al MK por separado para ATtiny13, ATtiny44, ATmega8 y ATmega128. Si ya ha conectado uno de estos MK para programar, como se sugiere en este artículo, puede flashearlo ahora mismo; obtendrá una caja de música. Más sobre esto a continuación.

Cuando selecciona la línea "Programador MK AVR" en el menú del script, el script comienza a ejecutarse. Al mismo tiempo, abre el puerto, envía un comando al MK para cambiar al modo de programación, recibe confirmación del MK sobre la transición exitosa, solicita el identificador del MK y busca una descripción de este MK por su identificador entre los disponibles archivos con descripciones. Si no encuentra la descripción requerida, muestra el mensaje correspondiente. Si se encuentra una descripción, se abre el menú principal del programador. Puede ver su captura de pantalla en la Figura 8. No es difícil comprenderlo mejor: el menú es muy simple.

En la primera versión del script, algunas funciones de un programador completo no están implementadas. Por ejemplo, no hay forma de leer ni escribir en EEPROM. Pero si abres el script en un editor de texto, verás que es de tamaño muy pequeño, a pesar de que lo principal ya está implementado en él. Esto sugiere que agregar las funciones que faltan no es tan difícil: el lenguaje es muy flexible y le permite implementar una rica funcionalidad en un programa pequeño. Pero en la mayoría de los casos, incluso las funciones existentes son suficientes.

Algunas limitaciones de funcionalidad se describen directamente en el texto del script:
//grabación implementada solo desde la dirección cero (el registro de dirección de segmento extendido se ignora, LOAD OFFSET también)
//el orden y la continuidad de los registros en el archivo HEX no están verificados
//la suma de comprobación no está marcada
Esto se aplica al trabajo con un archivo HEX, del cual se toma el código de firmware para MK. Si este archivo no está dañado, comprobar la suma de comprobación no tendrá ningún efecto. Si está distorsionado, no será posible detectarlo mediante el script. En la mayoría de los casos, las restricciones restantes no harán daño, pero aún así debes tenerlas en cuenta.

5. Caja de música: una manualidad sencilla para principiantes

Si tienes uno de estos microcontroladores: ATtiny13, ATtiny44, ATmega8 o ATmega128, puedes convertirlo fácilmente en una caja de música o una tarjeta de música. Para hacer esto, basta con escribir el firmware correspondiente en el MK, uno de esos cuatro que se encuentran en las carpetas "MusicBox_..." en el mismo archivo que el script. Los códigos de firmware se almacenan en archivos con la extensión ".hex". Usar ATmega128 para tal artesanía, por supuesto, es "graso", al igual que ATmega8. Pero esto puede resultar útil para pruebas o experimentación, en otras palabras, con fines educativos. También se adjuntan los textos de los programas en Assembler. Los programas no se crearon desde cero: se tomó como base el programa de la caja de música del libro de A.V. Belov. microcontroladores AVR en la práctica de la radioafición". El programa original ha sufrido una serie de cambios significativos:
1. adaptado para cada uno de los cuatro MK: ATtiny13, ATtiny44, ATmega8 y ATmega128
2. Se han eliminado los botones: no es necesario conectar nada al controlador excepto la alimentación y un emisor de sonido (las melodías se reproducen una tras otra en un bucle sin fin)
3. la duración de cada nota se reduce por la duración de la pausa entre notas para eliminar alteraciones en el ritmo musical
4. La octava melodía está conectada, no se usa en la versión del libro.
5. desde lo subjetivo: algunas “mejoras” para optimizar y hacer más fácil de entender el algoritmo

En algunas melodías se pueden escuchar falsedades e incluso errores graves, especialmente en “Smile”, en el medio. Los códigos de tono de llamada se tomaron del libro (o mejor dicho, se descargaron del sitio web del autor del libro junto con el archivo asm original) y no se modificaron. Al parecer, existen errores en la codificación de las melodías. Pero esto no es un problema: cualquiera que sea "amigable" con la música puede resolverlo fácilmente y arreglarlo todo.

En ATtiny13, debido a la falta de un contador de 16 bits, se tuvo que utilizar un contador de 8 bits para reproducir notas, lo que provocó una ligera disminución en la precisión de las notas. Pero esto apenas se nota de oído.

Sobre los bits de configuración. Sus configuraciones deben corresponder al estado del nuevo microcontrolador. Si su MK se ha utilizado antes en algún lugar, debe verificar el estado de sus bits de configuración y, si es necesario, alinearlos con la configuración del nuevo microcontrolador. Puede conocer el estado de los bits de configuración del nuevo microcontrolador en la documentación de este MK (sección "Bits de fusibles"). La excepción es ATmega128. Esta MCU tiene el bit M103C, que habilita el modo de compatibilidad con el ATmega103 anterior. La activación del bit M103C reduce en gran medida las capacidades del ATmega128 y este bit está activo en el nuevo MK. Debe restablecer el M103C a un estado inactivo. Para manipular los bits de configuración, utilice la sección correspondiente del menú del script del programador.

No tiene sentido dar un diagrama de la caja de música: solo contiene un microcontrolador, una fuente de alimentación y un emisor de sonido piezoeléctrico. La energía se suministra exactamente de la misma manera que lo hicimos al programar el MK. El emisor de sonido está conectado entre el cable común (pin GND del controlador) y uno de los pines MK, cuyo número se puede encontrar en el archivo con el código ensamblador del programa (*.asm). Al comienzo del texto del programa para cada MK en los comentarios hay una línea: " señal de sonido se forma en el pin XX". Cuando el script del programador completa su trabajo, el microcontrolador sale del modo de programación y entra en el modo de operación normal. La reproducción de melodías comienza inmediatamente. Al conectar el emisor de sonido, puede verificar esto. Puede salir del emisor de sonido conectado mientras se programa el cristal solo si el audio proviene de un pin no utilizado por el SPI; de lo contrario, la capacitancia adicional en el pin puede interferir con la programación.

Tarea: desarrollemos un programa para controlar un LED. Al pulsar el botón el LED se enciende y al soltarlo se apaga.

Primero, desarrollemos un diagrama esquemático del dispositivo. Los puertos de E/S se utilizan para conectar cualquier dispositivo externo al microcontrolador. Cada uno de los puertos es capaz de funcionar como entrada y salida. Conectemos el LED a uno de los puertos y el botón al otro. Para este experimento usaremos un controlador. Atmega8. Este chip contiene 3 puertos de E/S, 2 temporizadores/contadores de ocho bits y 1 de dieciséis bits. También a bordo hay un PWM de 3 canales, un convertidor analógico-digital de 10 bits de 6 canales y mucho más. En mi opinión, un microcontrolador es excelente para aprender los conceptos básicos de programación.

Para conectar el LED usaremos la línea PB0, y para leer información del botón usaremos la línea PD0. El diagrama se muestra en la Fig. 1.

Arroz. 1

A través de la resistencia R2, se suministra voltaje de alimentación adicional a la entrada PD0, que corresponde a una señal lógica. Cuando se cierra el botón, el voltaje cae a cero, lo que corresponde a un cero lógico. En el futuro, R2 se puede excluir del circuito reemplazándolo con una resistencia de carga interna e ingresando la configuración necesaria en el programa. El LED está conectado a la salida del puerto PB0 a través de la resistencia limitadora de corriente R3. Para encender el LED, debe aplicar una señal lógica a la línea PB0. Usaremos un generador de reloj maestro interno a 4 MHz, ya que el dispositivo no tiene altos requisitos de estabilidad de frecuencia.

Ahora escribimos el programa. Utilizo el entorno de programación para escribir programas. Estudio AVR Y WinAvr. Abra AVR Studio, aparece una ventana de bienvenida, haga clic en el botón "Crear un nuevo proyecto", luego seleccione el tipo de proyecto - AVR GCC, escriba el nombre del proyecto, por ejemplo "cod1", marque tanto "Crear carpeta de proyecto" como "Crear "Archivo de inicialización", haga clic en el botón "Siguiente", seleccione "AVR Simulator" en la ventana izquierda y escriba el microcontrolador "Atmega8" en la ventana derecha, haga clic en el botón "Finalizar", se abre el editor y el árbol de categorías del proyecto: el Se completan los ajustes iniciales.

Primero, agreguemos un texto de descripción estándar para Atmega8 usando el operador para adjuntar archivos externos: #incluir

sintaxis directiva #incluir

#incluir<имя_файла.h>
#incluir “nombre de archivo.h”

Paréntesis angulares< и >indique al compilador que los archivos incluidos deben buscarse primero en la carpeta estándar de WinAvr llamada include. Las comillas dobles " y " le indican al compilador que comience a buscar en el directorio donde está almacenado el proyecto.

Cada tipo de microcontrolador tiene su propio archivo de encabezado. Para ATMega8, este archivo se llama iom8.h, para ATtiny2313 - iotn2313.h. Al inicio de cada programa debemos incluir el archivo de cabecera del microcontrolador que estemos utilizando. Pero también existe un archivo de encabezado común io.h. El preprocesador procesa este archivo y, dependiendo de la configuración del proyecto, incluye el archivo de encabezado requerido en nuestro programa.

Para nosotros, la primera línea del programa se verá así:

#incluir

Cualquier programa en C debe contener una función principal. Se llama principal. La ejecución del programa siempre comienza con la ejecución de la función principal. Una función tiene un encabezado - int main(void) y un cuerpo - es limitada llaves {}.

int principal (vacío)
{
cuerpo funcional
}

Agregaremos nuestro código al cuerpo de la función. El tipo de retorno se indica antes del nombre de la función. Si la función no devuelve un valor, se utiliza la clave vacío.

En t- este es un número entero de 2 bytes, el rango de valores es de - 32768 a 32767

Después del nombre de la función, los parámetros que se pasan a la función cuando se llama se indican entre paréntesis (). Si la función no tiene parámetros, se utiliza la palabra clave. vacío. Función principal contiene un conjunto de comandos, configuraciones del sistema y el bucle principal del programa.

A continuación configuramos el puerto D en la entrada. El modo de funcionamiento del puerto está determinado por el contenido del registro. DDRD(registro de dirección de transferencia de información). Escribimos el número "0x00" (0b0000000 - en formato binario) en este registro; nada está conectado a este puerto excepto el botón, por lo que configuramos todo el puerto D como entrada. Puede configurar el puerto bit a bit escribiendo los números 0 o 1 en cada bit del registro (entrada 0, salida 1), por ejemplo DDRD = 0x81 (0b10000001): la primera y la última línea del puerto D funcionan como salida, el resto como entrada. También se debe conectar la resistencia de carga interna. El registro PORTx controla si las resistencias internas están activadas o desactivadas cuando el puerto está en modo de entrada. Escribamos unidades allí.

Configurando el puerto B a la salida. El modo de funcionamiento del puerto está determinado por el contenido del registro. DDRB. Nada más que un LED al puerto. B no está conectado, por lo que todo el puerto se puede configurar como salida. Esto se hace escribiendo al registro. DDRB números "0xFF". Para evitar que el LED se encienda cuando lo enciende por primera vez, escriba en el puerto B ceros lógicos. Esto se hace grabando PUERTO= 0x00;

Para asignar valores se utiliza el símbolo "=" y se denomina operador de asignación, que no debe confundirse con el signo "igual".

La configuración del puerto se verá así:

DDRD = 0x00;
PUERTO = 0xFF;
DDRB = 0xFF;
PUERTOB = 0x00;

Escribimos el bucle principal del programa. mientras(“mientras” del inglés): este comando organiza un bucle, repitiendo el cuerpo del bucle muchas veces hasta que se cumple la condición, es decir, mientras la expresión entre paréntesis sea verdadera. En C, una expresión se considera verdadera si no es igual a cero y falsa si lo es.

El comando se ve así:

mientras (condición)
{
cuerpo de bucle
}

En nuestro caso, el bucle principal constará de un solo comando. Este comando asigna el registro PUERTO valor del registro a invertir PORTADO.

PUERTOB = ~PIND; //tomar el valor del puerto D, invertirlo y asignarlo a PORTB (escribir en PORTB)

// Las expresiones C se leen de derecha a izquierda

PINTAR registro de entrada de información. Para leer información de la salida externa del controlador, primero debe cambiar el bit deseado del puerto al modo de entrada. Es decir, escribir en el bit correspondiente del registro. DDRx cero. Sólo después de esto se puede suministrar a este pin una señal digital desde un dispositivo externo. A continuación, el microcontrolador leerá el byte del registro. PINx. El contenido del bit correspondiente corresponde a la señal en el pin externo del puerto. Nuestro programa está listo y se ve así:

#incluir int main (void) ( DDRD = 0x00; //puerto D - entrada PORTD = 0xFF; //conecta la resistencia de carga DDRB = 0xFF; //puerto B - salida PORTB = 0x00; //establece la salida en 0 while(1 ) ( PORTB = ~PIND; //~ signo de inversión bit a bit ) )

Los comentarios se utilizan ampliamente en el lenguaje C. Hay dos formas de escribir.

/*Un comentario*/
//Un comentario

En este caso, el compilador no prestará atención a lo escrito en el comentario.

Si usa el mismo programa y conecta 8 botones y 8 LED al microcontrolador, como se muestra en la Figura 2, quedará claro que cada bit del puerto D coincide con su bit de puerto B. Al presionar el botón SB1 se enciende HL1, al presionar el botón SB2 se enciende HL2, etc.

Figura 2

El artículo utilizó materiales del libro de A.V. Belov. "Tutorial para desarrolladores de dispositivos AVR"

He dicho más de una o dos veces que estudiar MK debería comenzar con el ensamblador. Se dedicó un curso completo en el sitio web a esto (aunque no es muy consistente, pero poco a poco lo voy peinando hasta lograr una apariencia adecuada). Sí, es difícil, el resultado no estará el primer día, pero aprenderás a entender lo que sucede en tu controlador. Sabrás cómo funciona y no copiarás las fuentes de otras personas como un mono y tratarás de entender por qué de repente dejó de funcionar. Además, es mucho más fácil para C crear código sureño que saldrá con una horca en el momento más inoportuno.

Lamentablemente, todo el mundo quiere resultados inmediatos. Así que decidí ir por el otro lado: hacer un tutorial sobre C, pero mostrando su ropa interior. Un buen programador integrador siempre sujeta firmemente su pieza de hardware por el perno, sin permitirle dar un solo paso sin permiso. Entonces, primero estará el código C, luego lo que produjo el compilador y cómo funciona todo realmente :)

Por otro lado, el punto fuerte de C es la portabilidad del código. Si, por supuesto, escribes todo correctamente. Separar los algoritmos de trabajo y sus implementaciones hardware en diferentes partes del proyecto. Luego, para transferir el algoritmo a otro microcontrolador, bastará con reescribir solo la capa de interfaz, donde se escriben todas las llamadas al hardware, y dejar todo el código de trabajo como está. Y, por supuesto, legibilidad. El código fuente C es más fácil de entender a primera vista (aunque... por ejemplo, no me importa a qué señalar, ya sea C o ASM :)), pero, nuevamente, si todo está escrito correctamente. También prestaré atención a estos puntos.

Mi placa de depuración servirá como hardware experimental en el que se instalará la mayor parte de todos los ejemplos.

El primer programa C para AVR

Elegir un compilador y configurar el entorno.
Hay muchos compiladores de C diferentes para AVR:
Primero que todo esto IAR AVR C- es casi definitivamente reconocido como el mejor compilador para AVR, porque El controlador en sí fue creado en estrecha colaboración entre Atmel y especialistas de IAR. Pero hay que pagar por todo. Y este compilador no solo es un software comercial costoso, sino que también tiene tantas configuraciones que requiere mucho esfuerzo simplemente compilarlo en él. Realmente no desarrollé una amistad con él; el proyecto se estaba pudriendo debido a errores extraños en la etapa de vinculación (más tarde descubrí que era una grieta torcida).

lo segundo viene WinAVR GCC- un potente compilador de optimización. Totalmente de código abierto, multiplataforma, en general, todos los placeres de la vida. También se integra perfectamente en AVR Studio, lo que le permite depurar allí mismo, lo cual es muy conveniente. En general lo elegí.

También hay CodeVision AVR C es un compilador muy popular. Se hizo popular por su sencillez. Puede obtener un programa que funcione en solo unos minutos; el asistente del código de inicio facilita enormemente esto al eliminar estándares para la inicialización de todo tipo de cosas. Para ser honesto, sospecho un poco de esto: una vez que tuve que desmantelar un programa escrito por este compilador, resultó ser una especie de desastre y no código. Una cantidad terrible de movimientos y operaciones innecesarias, que resultaban en una cantidad considerable de código y un rendimiento lento. Sin embargo, tal vez hubo un error en el ADN de la persona que escribió el firmware original. Además quiere dinero. No tanto como IAR, pero sí notable. Y en modo demo te permite escribir no más de 2kb de código.
Claro que hay un crack, pero si vas a robar, es un millón, en el sentido IAR :)

También hay Imagen Craft AVR C Y MicroC de la microelectrónica. No tuve que usar ninguno de los dos, pero S.W.G. muy elogioso MicroPascal, dicen, un entorno de programación y bibliotecas terriblemente convenientes. Creo que MicroC no será peor, pero también es de pago.

Como dije, elegí WinAVR por tres razones: es gratis, se integra en AVR Studio y hay un montón de código listo para usar escrito para todas las ocasiones.

Descargue la instalación de WinAVR con AVR Studio. A continuación, primero se instala el estudio, luego se coloca WinAVR encima y se conecta al estudio en forma de complemento. Recomiendo encarecidamente instalar WinAVR en una ruta corta, algo así como C:\WinAVR, de esta manera evitará muchos problemas con las rutas.

Creando un proyecto
Entonces, el estudio está instalado, C está atornillado, es hora de intentar programar algo. Empecemos por lo simple, lo más sencillo. Inicie el estudio, seleccione un nuevo proyecto allí, como compilador AVR GCC e ingrese el nombre del proyecto.

Se abre un campo de trabajo con un archivo *.c vacío.

Ahora no estará de más configurar la visualización de rutas en los marcadores del estudio. Para hacer esto, vaya a:
Menú Herramientas - Opciones - General - Fichas Archivo y seleccione "Solo nombre de archivo" en la lista desplegable. De lo contrario, será imposible trabajar: la pestaña contendrá la ruta completa del archivo y no habrá más de dos o tres pestañas en la pantalla.

Configuración del proyecto
En general, se considera clásico crear un archivo make en el que se describen todas las dependencias. Y eso probablemente sea correcto. Pero para mí, que crecí con IDE totalmente integrados como uVisión o Estudio AVR Este enfoque es profundamente extraño. Por eso lo haré a mi manera, todo utilizando medios de estudio.

Presiona el botón con el engranaje.


Estas son las configuraciones de su proyecto, y ajustes más precisos generación automática de makefile. En la primera página sólo necesita ingresar la frecuencia a la que funcionará su MK. Esto depende de los bits del fusible, por lo que asumimos que nuestra frecuencia es 8000000Hz.
También preste atención a la línea de optimización. Ahora está -Os: esto es optimización de tamaño. Déjalo como está por ahora, luego podrás intentar jugar con este parámetro. -O0 no es ninguna optimización.

El siguiente paso es configurar las rutas. En primer lugar, agregue el directorio de su proyecto allí; agregará bibliotecas de terceros allí. La ruta “.\” aparecerá en la lista.

El archivo Make ha sido generado, puedes verlo en la carpeta predeterminada de tu proyecto, solo echa un vistazo y mira qué hay allí.


Eso es todo por ahora. Haga clic en Aceptar en todas partes y vaya a la fuente.

Formulación del problema
Una hoja de papel en blanco es tentadora para implementar alguna idea astuta, ya que el banal parpadeo de un diodo ya no funciona. Inmediatamente tomemos el toro por los cuernos e implementemos la conexión con la computadora; esto es lo primero que hago.

Funcionará así:
Cuando llegue un uno (código 0x31) por el puerto COM encenderemos el diodo, y cuando llegue un cero (código 0x30) se apagará. Además, todo se hará mediante interrupciones y la tarea en segundo plano será el parpadeo de otro diodo. Sencillo y significativo.

Montaje del circuito
Necesitamos conectar el módulo convertidor USB-USART a los pines USART del microcontrolador. Para hacer esto, tome un puente de dos cables y colóquelo en los pines en forma transversal. Es decir, conectamos el Rx del controlador al Tx del convertidor, y el Tx del convertidor al Rx del controlador.

Al final este es el diagrama:


No considero conectar los pines restantes, alimentación o reinicio, es estándar.

Escribir código

Permítanme hacer una reserva de inmediato de que no profundizaré específicamente en la descripción del lenguaje C en sí. Simplemente hay una cantidad colosal de material para esto, que va desde el clásico "lenguaje de programación C" de K&R hasta varios manuales.

Encontré uno de esos métodos en mi escondite; una vez lo usé para estudiar este idioma. Todo allí es breve, claro y va al grano. Poco a poco lo estoy armando y arrastrándolo a mi sitio web.

Es cierto que aún no se han transferido todos los capítulos, pero creo que no será por mucho tiempo.

Es poco probable que pueda describirlo mejor, por lo que desde el curso de capacitación, en lugar de una explicación detallada de las sutilezas, simplemente proporcionaré enlaces directos a páginas individuales de este manual.

Agregar bibliotecas.
En primer lugar, agregamos las bibliotecas y encabezados con definiciones necesarios. Después de todo, C es un lenguaje universal y debemos explicarle que estamos trabajando específicamente con AVR, así que escriba la línea en el código fuente:

1 #incluir

#incluir

Este archivo se encuentra en la carpeta WinAVR y contiene una descripción de todos los registros y puertos del controlador. Además, todo es astuto, con enlace a un controlador específico, que es transmitido por el compilador a través de hacer archivo en parámetro MCU y en función de esta variable, se conecta un archivo de encabezado a su proyecto con una descripción de las direcciones de todos los puertos y registros para este controlador en particular. ¡Guau! Sin él, también es posible, pero entonces no podrás usar nombres de registros simbólicos como SREG o UDR y tendrás que recordar la dirección de cada uno como “0xC1”, lo cual será un dolor de cabeza.

El equipo mismo #incluir<имя файла> le permite agregar contenido de cualquier tipo a su proyecto Archivo de texto, por ejemplo, un archivo con una descripción de funciones o un fragmento de otro código. Y para que la directiva pueda encontrar este archivo, especificamos la ruta a nuestro proyecto (el directorio WinAVR ya está registrado allí de forma predeterminada).

Función principal.
Un programa en C se compone enteramente de funciones. Se pueden anidar y llamar entre sí en cualquier orden y diferentes caminos. Cada función tiene tres parámetros requeridos:

  • El valor de retorno es p.e. pecado(x) devuelve el valor del seno de x. Como en matemáticas, en definitiva.
  • Los parámetros transmitidos son los mismos X.
  • Cuerpo funcional.

Todos los valores transmitidos y devueltos deben ser de algún tipo, dependiendo de los datos.

Cualquier programa en C debe contener una función. principal como punto de entrada al programa principal; de lo contrario, no es C en absoluto :). Por la presencia de main en el código fuente de otra persona de un millón de archivos, se puede entender que esta es la parte principal del programa, donde comienza todo. Entonces preguntémonos:

1 2 3 4 5 int principal (vacío) (devuelve 0;)

int principal (vacío) (devuelve 0;)

Eso es todo, primero programa más simple escrito, no importa que no haga nada, recién comenzamos.

Averigüemos qué hicimos.
En t Este es el tipo de datos que devuelve la función principal.

Por supuesto, en un microcontrolador. principal en principio no se puede devolver nada y en teoría debería haber vacío principal (vacío), pero GCC fue diseñado originalmente para PC y allí el programa puede devolver el valor Sistema operativo al finalizar. Por lo tanto, GCC en vacío principal (vacío) jura por Advertencia.

Esto no es un error, funcionará, pero no me gustan las advertencias.

vacío este es el tipo de datos que le pasamos a la función, en este caso principal Tampoco puedo aceptar nada del exterior, por lo tanto vacío- un muñeco. Un stub se utiliza cuando no hay necesidad de transmitir ni devolver nada.

Aquí están { } Las llaves son un bloque de programa, en este caso el cuerpo de una función. principal, el código se ubicará allí.

devolver- este es el valor de retorno que devolverá la función principal al finalizar, ya que tenemos un int, es decir un número, entonces debemos devolver un número. Aunque esto todavía no tiene sentido, porque... en el microcontrolador, no podemos ir a ninguna parte desde main. Devuelvo nulo. Porque no importa. Pero el compilador suele ser inteligente y no genera código para este caso.
Aunque, si es pervertido, entonces de principal Puede ir al MK; por ejemplo, ingresar a la sección del cargador de arranque y ejecutarlo, pero esto requerirá retoques de bajo nivel con el firmware para corregir las direcciones de transición. A continuación podrá comprobarlo usted mismo y comprender cómo hacerlo. ¿Para qué? Esta es otra cuestión, en el 99,999% de los casos esto no es necesario :)

Lo hicimos y seguimos adelante. Agreguemos una variable, realmente no la necesitamos y no tiene sentido introducir variables sin ella, pero estamos aprendiendo. Si se agregan variables dentro del cuerpo de una función, entonces son locales y existen solo en esta función. Cuando sale de la función, estas variables se eliminan y la memoria RAM se asigna para necesidades más importantes. .

1 2 3 4 5 6 int main(void) (carácter sin firmar i; devolver 0;)

int main(void) (carácter sin firmar i; devuelve 0;)

no firmado significa sin firmar. El hecho es que en la representación binaria, el bit más significativo se asigna al signo, lo que significa que el número +127/-128 cabe en un byte (char), pero si se descarta el signo, cabrá de 0 a 255. Generalmente no se necesita el signo. Entonces no firmado.
i es solo un nombre de variable. No más.

Ahora necesitamos inicializar los puertos y UART. Por supuesto, puede tomar y conectar la biblioteca y llamar a algún tipo de UartInit(9600); pero entonces no sabrás lo que realmente pasó.

Nosotros hacemos esto:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int main(void) (carácter sin firmar i; #definir XTAL 8000000L #definir velocidad en baudios 9600L #definir divisor de baudios (XTAL/(16*velocidad de baudios)-1)#definir HI(x) ((x)>>8) #definir LO(x) ((x)& 0xFF) UBRRL = LO(divisor de baudios); UBRRH = HI(divisor de baudios); UCSRA = 0; UCSRB = 1<< RXEN| 1 << TXEN| 1 << RXCIE| 0 << TXCIE; UCSRC = 1 << URSEL| 1 << UCSZ0| 1 << UCSZ1; }

int main(void) (unsigned char i; #definir XTAL 8000000L #definir velocidad en baudios 9600L #definir divisor en baudios (XTAL/(16*velocidad en baudios)-1) #definir HI(x) ((x)>>8) #definir LO( x) ((x)& 0xFF) UBRRL = LO(divisor de baudios); UBRRH = HI(divisor de baudios); UCSRA = 0; UCSRB = 1<

¿Aterrador? De hecho, sólo hay cinco últimas líneas de código real. Todo que #definir es un lenguaje de macros preprocesador. Casi lo mismo que en Asamblea, pero la sintaxis es ligeramente diferente.

Facilitarán sus operaciones rutinarias de cálculo de los coeficientes necesarios. En la primera línea decimos que en lugar XTAL puedes sustituir con seguridad 8000000, y l- indicación del tipo, diciendo long es la frecuencia de reloj del procesador. Lo mismo velocidad en baudios— frecuencia de transmisión de datos a través de UART.

divisor de baudios ya es más complicado, en su lugar se sustituirá la expresión calculada mediante la fórmula de las dos anteriores.
Bien y L.O. Y HOLA los bytes bajos y altos se tomarán de este resultado, porque Obviamente, es posible que no quepa en un byte. EN HOLA X (el parámetro de entrada de macro) se desplaza ocho veces hacia la derecha, lo que da como resultado que solo quede el byte más significativo. Y en L.O. Hacemos un AND bit a bit con el número 00FF, como resultado solo quedará el byte bajo.

Entonces todo lo que se hace es como #definir puede tirarlo con seguridad y calcular los números necesarios en una calculadora e ingresarlos inmediatamente en las líneas UBBRL =…. y UBBRH = …..

Poder. ¡Pero! Hacer esto ABSOLUTAMENTE IMPOSIBLE!

Funcionará de esta manera o de aquella, pero tendrás lo que se llama numeros magicos- valores tomados de la nada y por razones desconocidas, y si abres un proyecto de este tipo en un par de años, será muy difícil entender cuáles son estos valores. Incluso ahora, si quieres cambiar la velocidad, o cambiar la frecuencia del cuarzo, tendrás que volver a calcular todo, pero cambiaste un par de números en el código y listo. En general, si no desea que lo tilden de codificador, cree su código de manera que sea fácil de leer, comprensible y fácil de modificar.

Entonces todo es sencillo:
Todos estos "UBRRL and Co" son registros de configuración del transmisor UART con la ayuda del cual nos comunicaremos con el mundo. Y ahora les hemos asignado los valores requeridos, configurándolos en la velocidad y modo deseados.

Tipo de grabación 1< Significa lo siguiente: tomar 1 y ponerlo en su lugar RXEN en bytes. RXEN este es el cuarto bit del registro UCSRB, Entonces 1< forma el número binario 00010000, TXEN- este es el tercer bit, y 1< dará 00001000. Sencillo "|" es bit a bit O, entonces 00010000 | 00001000 = 00011000. De la misma manera, los bits de configuración necesarios restantes se configuran y agregan al montón general. Como resultado, el número recaudado se registra en la UCSRB. Se describen más detalles en la hoja de datos del MK en la sección USART. Así que no nos distraigamos con detalles técnicos.

Listo, es hora de ver qué pasó. Haga clic en compilación e inicie la emulación (Ctrl+F7).

Depuración
Pasaron todo tipo de barras de progreso, el estudio cambió y apareció una flecha amarilla cerca de la entrada a la función principal. Aquí es donde el procesador está funcionando actualmente y la simulación está en pausa.

El caso es que inicialmente, de hecho, estaba en la línea UBRRL = LO(bauddivider); Después de todo, lo que tenemos en definición no es código, sino simplemente cálculos preliminares, razón por la cual el simulador es un poco aburrido. Pero ahora se dio cuenta, la primera instrucción ha sido completada y si subes al árbol Vista de E/S, a la sección USART y mira el byte UBBRL allí, verás que el valor ya está ahí. 0x33.

Vaya un paso más allá. Vea cómo cambia el contenido del otro registro. Así que revíselos todos, preste atención al hecho de que todos los bits indicados están configurados como le dije, y están configurados simultáneamente para todo el byte. No irá más allá de Regresar: el programa ha terminado.

Apertura
Ahora restablezca la simulación a cero. Haga clic allí Restablecer (Mayús+F5). Abra la lista desensamblada, ahora verá lo que realmente está sucediendo en el controlador. Ver -> Desensamblador. ¡¡¡Y no YYAAAAAA!!! ¡¡¡Ensamblador!!! ¡¡¡HORROR!!! Y ES NECESARIO. Para que luego, cuando algo salga mal, no seas estúpido en el código y no hagas preguntas tontas en los foros, sino que inmediatamente entres en el fondo y veas dónde estás atascado. No hay nada aterrador allí.

Primero estarán los mejores de la serie:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 +00000000: 940C002A JMP 0x0000002A Salto +00000002: 940C0034 JMP 0x00000034 Salto +00000004: 940C0034 JMP 0x00000034 Salto +00000006: 940C0034 J MP 0 x00000034 Salto +00000008: 940C0034 JMP 0x00000034 Salto +0000000A: 940C0034 JMP 0x00000034 Salto +0000000C: 940C0034 JMP 0x00000034 Salto + 0000000E: 940C0034 JMP 0x00000034 Salto +00000010: 940C0034 JMP 0x00000034 Salto +00000012: 940C0034 JMP 0x00000034 Salto +00000014: 940C0034 J MP 0x00000034 Salto +00000016: 940C0034 JMP 0x00000034 Salto +00000018: 940C0034 JMP 0x00000034 Salto +0000001A: 940C0034 JMP 0x00000034 Salto +000000 1C: 940C0034 JMP 0x00000034 Salto +0000001E: 940C0034 JMP 0x00000034 Salto +00000020: 940C0034 JMP 0x00000034 Salto +00000022: 940C0034 JMP 0x0000 0034 Salto +00000024: 940C0034 JMP 0x00000034 Salto +00000026: 940C0034 JMP 0x00000034 Salto +00000028: 940C0034 JMP 0x00000034 Saltar

00000000: 940C002A JMP 0x0000002A Salto +00000002: 940C0034 JMP 0x00000034 Salto +00000004: 940C0034 JMP 0x00000034 Salto +00000006: 940C0034 J MP 0 x00000034 Salto +00000008: 940C0034 JMP 0x00000034 Salto +0000000A: 940C0034 JMP 0x00000034 Salto +0000000C: 940C0034 JMP 0x00000034 Salto + 000000 0E: 940C0034 JMP 0x00000034 Salto +00000010: 940C0034 JMP 0x00000034 Salto +00000012: 940C0034 JMP 0x00000034 Salto +00000014: 940C0034 JMP 0x0000 0034 Salto +00000016: 940C0034 JMP 0x00000034 Salto +00000018: 940C0034 JMP 0x00000034 Salto +0000001A: 940C0034 JMP 0x00000034 Salto +0000001C: 940C0034 JMP 0x00000034 Salto +0000001E: 940C0034 JMP 0x00000034 Salto +00000020: 940C0034 JMP 0x00000034 Salto +00000022: 940C0034 JMP 0 x000000 34 Salto +00000024: 940C0034 JMP 0x00000034 Salto +00000026: 940C0034 JMP 0x00000034 Salto +00000028: 940C0034 JMP 0x00000034 Salto

Esta es la tabla de vectores de interrupción. Volveremos a ello más adelante, pero por ahora sólo mira y recuerda que existe. La primera columna es la dirección de la celda flash en la que se encuentra el comando, la segunda es el código del comando, la tercera es el mnemotécnico del comando, la misma instrucción de ensamblaje, la tercera son los operandos del comando. Bueno, comentario automático.
Entonces, si nos fijamos, hay transiciones continuas. Y el código de comando JMP tiene cuatro bytes y contiene la dirección de salto escrita al revés: el byte bajo en la dirección baja y el código de comando de salto 940C.

0000002B: BE1F OUT 0x3F,R1 Salida a ubicación de E/S

Grabando este cero en la dirección 0x3F. Si observa la columna de vista de E/S, verá que la dirección 0x3F es la dirección del registro SREG, el registro de bandera del controlador. Aquellos. Reiniciamos SREG para ejecutar el programa en condiciones cero.

1 2 3 4 +0000002C: E5CF LDI R28,0x5F Carga inmediata +0000002D: E0D4 LDI R29,0x04 Carga inmediata +0000002E: BFDE OUT 0x3E,R29 Salida a ubicación de E/S +0000002F: BFCD OUT 0x3D,R28 Salida a ubicación de E/S

0000002C: E5CF LDI R28,0x5F Carga inmediata +0000002D: E0D4 LDI R29,0x04 Carga inmediata +0000002E: BFDE OUT 0x3E,R29 Salida a ubicación de E/S +0000002F: BFCD OUT 0x3D,R28 Salida a ubicación de E/S

Esto está cargando el puntero de la pila. No puede cargar directamente en registros de E/S, sólo a través de un registro intermedio. Por lo tanto, primero LDI al intermedio y luego de ahí OUT a E/S. También les contaré más sobre la pila más adelante. Por ahora, sepa que se trata de un área de memoria dinámica que se cuelga al final de la RAM y almacena direcciones y variables intermedias. Ahora hemos indicado desde dónde comenzará nuestra pila.

00000032: 940C0041 JMP 0x00000041 Salto

Vaya al final del programa, y ​​allí tenemos la prohibición de interrupciones y bucles cerrados sobre sí mismo:

1 2 +00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Salto relativo

00000041: 94F8 CLI Global Interrupt Disable +00000042: CFFF RJMP PC-0x0000 Salto relativo

Esto es en caso de circunstancias imprevistas, como salir de la función principal. El controlador puede salir de dicho bucle mediante un reinicio del hardware o, más probablemente, mediante un reinicio desde un dispositivo de vigilancia. Bueno, o, como dije anteriormente, corregir esto en el editor hexadecimal y galopar hacia donde nuestro corazón desee. También tenga en cuenta que hay dos tipos de transiciones: JMP y RJMP; la primera es una transición directa a una dirección. Ocupa cuatro bytes y puede saltar directamente a través de toda el área de memoria. El segundo tipo de transición es RJMP, relativa. Su comando ocupa dos bytes, pero se mueve desde la posición actual (dirección) 1024 pasos hacia adelante o hacia atrás. Y sus parámetros indican el desplazamiento desde el punto actual. Se usa más a menudo porque Ocupa la mitad del espacio en una descarga y rara vez se necesitan transiciones largas.

1 +00000034: 940C0000 JMP 0x00000000 Salto

00000034: 940C0000 JMP 0x00000000 Salto

Y este es un salto al principio del código. Una especie de reinicio. Puedes comprobar que todos los vectores saltan aquí. La conclusión de esto es que si ahora habilita las interrupciones (están deshabilitadas de manera predeterminada) y su interrupción ocurre pero no hay un controlador, entonces habrá un reinicio del software: el programa volverá al principio.

Función principal. Todo es parecido, ni siquiera hace falta describirlo. Basta con mirar el número ya calculado que se ingresa en los registros. ¡¡¡El preprocesador del compilador es genial!!! ¡Así que nada de números “mágicos”!

1 2 3 4 5 6 7 8 9 10 11 12 <

00000036: E383 LDI R24,0x33 Carga inmediata +00000037: B989 OUT 0x09,R24 Salida a la ubicación de E/S 15: UBRRH = HI(divisor de baudios); +00000038: BC10 OUT 0x20,R1 Salida a la ubicación de E/S 16: UCSRA = 0; +00000039: B81B OUT 0x0B,R1 Salida a la ubicación de E/S 17: UCSRB = 1<

Y aquí está el error:

1 2 3 +0000003E: E080 LDI R24.0x00 Carga inmediata +0000003F: E090 LDI R25.0x00 Carga inmediata +00000040: 9508 RET Retorno de subrutina

0000003E: E080 LDI R24.0x00 Carga inmediata +0000003F: E090 LDI R25.0x00 Carga inmediata +00000040: 9508 RET Retorno de subrutina

La pregunta es, ¿por qué el compilador agrega esos picos? Y esto no es más que Retorno 0, definimos la función como int main(void) y por eso desperdiciamos otros cuatro bytes para nada :) Y si haces void main(void) entonces solo quedará RET, pero aparecerá una advertencia , que nuestra función principal no devuelve nada. En general, haz lo que quieras :)

¿Difícil? Aparentemente no. Haga clic en ejecución paso a paso en modo desensamblador y vea cómo el procesador ejecuta instrucciones individuales, qué sucede con los registros. ¿Cómo se produce el movimiento a través de comandos y el bucle final?

Continuará en un par de días...

Por encima:
Alexei78 Creé un complemento para Firefox que facilita la navegación por mi sitio y foro.
Discusión y descarga,


La radioafición moderna no se puede imaginar sin microcontroladores, y esto es obvio. En las últimas décadas, los microcontroladores de diversos fabricantes se han generalizado en diversos campos de la actividad humana. A menudo se pueden encontrar en los dispositivos y diseños más inesperados. Usted y yo somos testigos de la informatización y automatización de los procesos que nos rodean. La verdad es que sin conocimientos de los conceptos básicos de programación, se ha vuelto casi imposible crear dispositivos competitivos modernos...

Si está leyendo este artículo, probablemente desee comprender cómo funcionan los microcontroladores y probablemente tenga preguntas:

4. ¿Qué literatura debo estudiar?

Intentemos responder a estas preguntas.

1. ¿Qué microcontrolador debo elegir para el trabajo?

Los microcontroladores de 8 bits son muy populares entre los radioaficionados. FOTO Tecnología de microchips y AVR Atmel, 16 bits MSP430 de TI, así como microcontroladores de 32 bits, arquitecturas BRAZO.

En la industria, de manera algo diferente, el primer lugar lo ocupan con diferencia Electrónica Renesas en el segundo escala libre, en el tercero Samsung, entonces vete Pastilla Y TI, luego todo lo demás.
La popularidad está determinada por el precio y la disponibilidad; la disponibilidad de información técnica y el costo del soporte del software juegan un papel importante.

Estudiaremos microcontroladores AVR de 8 bits, familias. Serie ATMEGA 8 y 16. La elección estuvo determinada, nuevamente, por la accesibilidad, la presencia de muchos desarrollos de aficionados y una gran cantidad de material educativo. La presencia de una variedad de componentes integrados y la funcionalidad de esta familia.

2. ¿Qué entorno de desarrollo debo utilizar para programar el microcontrolador seleccionado?

Se han creado varios entornos de desarrollo integrados (IDE, entorno de desarrollo integrado) para AVR.
IDE es un sistema de software utilizado por programadores para desarrollar software, que incluye:
editor de texto,
compilador y/o intérprete,
herramientas de automatización de montaje,
depurador

Los mas comunes AVRStudio, ATmelStudio, WINAVR, CodeVision, banco de trabajo integrado IAR.
Para escribir programas, usaremos el software gratuito. IDE ATmelStudio versión 6 y más alto.
Puede descargar Atmel Studio desde el sitio web oficial después de registrarse (¡el registro es absolutamente gratuito y no lo obliga a nada!)

ATmelStudio le permite crear proyectos y escribir programas tanto en ensamblador como en SI.

Inicialmente, la pregunta siempre es: ¿qué lenguaje de programación debo elegir para escribir programas eficaces?

Mi respuesta es simple: necesitas poder escribir en al menos dos idiomas: ensamblador y SI. El lenguaje ensamblador es simplemente necesario cuando necesita escribir subrutinas y macros rápidas y compactas, y varios controladores de dispositivos. Pero, cuando es necesario crear un gran proyecto basado en algoritmos complejos, sin conocimientos de SI, se puede dedicar mucho tiempo, especialmente en el proceso de depuración, y si se desea transferirlo a otra plataforma, por ejemplo PIC18. , o STM, puede convertirse en un problema insoluble.
Además, ahora han aparecido plataformas informáticas de hardware. arduino, cuyo trabajo requiere conocimientos del lenguaje SI++.
Por tanto, escribiremos programas tanto en ensamblador como en SI.

Para ver claramente el resultado de su trabajo sin usar un soldador o una placa de pruebas, simplemente instale el programa Proteo.

3. ¿Cómo flashear el controlador y qué dispositivos y accesorios adicionales se necesitan para trabajar cómodamente con ellos?

Usamos Datagoriano. Además, necesitarás comprar placas de prueba y una fuente de alimentación con un voltaje de salida de 5 voltios. Puede usarlo como fuente de alimentación de baja ondulación mediante el uso de un diodo zener de 5 voltios.
Quizás, con el tiempo, Igor y yo propongamos un proyecto para ensamblar una placa de depuración.

4. ¿Qué literatura debo estudiar?

Pero, por ejemplo:
Programación práctica de AVR en ensamblador. Revich, 2011
1000 y un circuito microcontrolador Vol. 1-2. Ryumik, 2010-2011
10 dispositivos prácticos en el AVR MK Libro 1-2. Krávchenko, 2008-2009
Un tutorial para desarrolladores de dispositivos que utilizan AVR MK. Belov, 2008
Familias MK AVR Tiny y Atmega. Efstifeev, 2008
CódigoVisionAVR. Una guía para principiantes. Lébedev, 2008
Control por microprocesador de dispositivos, tiristores, relés. Belov, 2008
Interfaces analógicas MK. Mayordomo, pelota, 2007
Creamos dispositivos en el AVR MK. Belov, 2007
MK AVR en la práctica de radioaficionados. Análisis completo de ATTINY2313. Belov, 2007
Intercambio de datos de red e interconexión con MK. Ir, 2007
MK AVR. Taller para principiantes. Hartov, 2007
Aplicación de Esquemas, algoritmos, programas AVR. Baránov, 2006
Microcontroladores AVR. Curso de introducción. Mortón, 2006
Medición, control y regulación mediante AVR. Trumpert, 2006
Programación en lenguaje C para AVR y PIC MK. Shpak, 2006
Diseño de dispositivos en MK. Belov, 2005
MK: es simple, volúmenes 1-3. Frunzé, 2002-2003
El lenguaje de programación C, segunda edición. Kernighan, Ritchie, 2009
Programación de microcontroladores ATMEL en el lenguaje S. Prokopenko, 2012

5. ¿En qué parte de Internet puedes hacer preguntas y obtener respuestas específicas?

Puede hacer preguntas en nuestro foro o en cualquier otro donde se traten temas sobre microcontroladores de una forma u otra. Lo principal en los foros es formular correctamente las preguntas para poder recibir respuestas claras. Las preguntas abstractas no son bienvenidas y lo más probable es que reciba duras críticas en lugar de una respuesta, ¡o su pregunta quedará sin respuesta!

Ahora echemos un vistazo más de cerca a nuestro favorito, el microcontrolador ATMEGA 8.

Microcontrolador AVR de 8 bits, alto rendimiento y bajo consumo
Arquitectura RISC progresiva
130 instrucciones de alto rendimiento, la mayoría de las instrucciones ejecutadas en un ciclo de reloj
32 registros de trabajo de propósito general de 8 bits
Funcionamiento completamente estático
Acercándose al rendimiento de 16 MIPS (a 16 MHz)
Multiplicador de 2 ciclos incorporado

Memoria no volátil de programas y datos.
8 KB de memoria flash autoprogramable en el sistema
Proporciona 1000 ciclos de borrado/escritura
Sector de código de arranque adicional con bits de bloqueo independientes
Proporciona modo de lectura/escritura simultánea (lectura-mientras-escritura)
EEPROM de 512 bytes
Proporciona 100.000 ciclos de borrado/escritura
1 KB de SRAM en chip
Bloqueo programable para proteger el software del usuario

Periféricos integrados
Dos temporizadores/contadores de 8 bits con preescalador separado, uno con modo de comparación
Un temporizador/contador de 16 bits con preescalador independiente y modos de captura y comparación
Contador en tiempo real con generador independiente
Tres canales PWM
Convertidor A/D de 8 canales (TQFP y MLF)
6 canales con precisión de 10 bits
Convertidor analógico a digital de 6 canales (en paquete PDIP)
4 canales con precisión de 10 bits
2 canales con precisión de 8 bits
Interfaz serie de 2 hilos orientada a bytes
USART serie programable
Interfaz serie SPI (maestro/esclavo)
Temporizador de vigilancia programable con oscilador incorporado independiente
Comparador analógico incorporado

Funciones especiales del microcontrolador
Reinicio de encendido y detección de caída de tensión programable
Oscilador RC calibrado incorporado
Fuentes de interrupción internas y externas
Cinco modos de bajo consumo: inactivo, ahorro de energía, apagado, espera y reducción de ruido ADC

Pines y carcasas de E/S
23 líneas de E/S programables
Paquete PDIP de 28 pines, paquete TQFP de 32 pines y paquete MLF de 32 pines

Tensiones de funcionamiento
2,7 - 5,5 V (ATmega8L)
4,5 - 5,5 V (ATmega8)

Frecuencia de operación
0 - 8 MHz (ATmega8L)
0 - 16 MHz (ATmega8)

diferencias entre ATMEGA16 y 8
16 KB de memoria flash autoprogramable en el sistema

Interfaz JTAG (compatible con IEEE 1149.1)
Capacidad de escaneo periférico compatible con el estándar JTAG
Soporte ampliado para la depuración integrada
Programación vía interfaz JTAG: Flash, memoria EEPROM, jumpers y bits de bloqueo

Cuatro canales PWM/PWM

Convertidor analógico a digital de 8 canales y 10 bits
8 canales no balanceados
7 canales diferenciales (solo paquete TQFP)
2 canales diferenciales con ganancia programable de 1x, 10x o 200x (solo paquete TQFP)

Seis modos de bajo consumo: inactivo, ahorro de energía, apagado, espera, espera extendida y reducción de ruido ADC

32 líneas de E/S programables

Paquete PDIP de 40 pines y paquete TQFP de 44 pines

AtmelStudio

Si recién está comenzando, debe descargar e instalar el programa AtmelStudio desde la página oficial atmel.com
Después de instalar el programa AtmelStudio, puede comenzar a crear un proyecto.
Proyecto- este es su programa que escribirá, depurará y flasheará, después de la compilación, en la memoria del microcontrolador.

Para crear un proyecto, debe abrir el programa, aparecerá el siguiente protector de pantalla:

y se abrirá la página de creación del proyecto.

Para crear un nuevo proyecto, debe hacer clic en "Nuevo proyecto..."
En este caso, se abrirá una nueva ventana donde podrá seleccionar el lenguaje de programación, el nombre del proyecto, su ubicación, el nombre del paquete con los archivos del proyecto y la posibilidad de crear un directorio para su uso posterior en otros proyectos cruzados. . Para crear un proyecto donde programaremos en ensamblador, debemos seleccionar: Ensamblador, luego de eso cambiamos el nombre del proyecto, su ubicación y seleccionamos DE ACUERDO.

La siguiente ventana aparecerá

Elegir “megaAVR, 8 bits” y encontramos el microcontrolador que necesitamos, elegimos ATmega8. En la parte derecha del protector de pantalla aparece una lista de dispositivos que funcionan con este microcontrolador, uno de los cuales podemos conectar. Elegir DE ACUERDO.

Aparece la página del editor de texto, que le permite editar y depurar el programa. Mientras la página está en blanco, se indican la hora y fecha de creación y el nombre del archivo del proyecto, nombre de usuario. Hay una ventana de dispositivos de E/S adicionales y una ventana de informes de compilación de programas. ahora nosotros


Podemos programar en ensamblador.
De la misma forma se crea un proyecto de programación en lenguaje SI.

¡Hola, residentes de MySku! El héroe de nuestra revisión es el microcontrolador Atmega8A-16PU. Le contaré cómo programar este microcontrolador en el entorno de desarrollo integrado CodeVisionAvr, haremos parpadear el LED y consideraremos los pros y los contras de trabajar en este entorno. Quizás en el futuro esto le sirva como alternativa al ya “popular” Arduino. Si estás interesado, ve a cortar.

Preámbulo.
Dio la casualidad de que comencé a conocer MK con Arduino. Parpadeé el LED, conecté varios sensores y escudos e hice varios proyectos. Todo funcionó, quedé satisfecho, pero quería algo más. Me encontré con un proyecto en el que participa Atmega8A, para el cual necesito escribir el firmware yo mismo. Fue él quien me impulsó a estudiar el proceso de programación de un MK "desnudo".
Entonces, tenemos un microcontrolador de Atmel, la familia AVR Atmega8A.

Especificaciones:


Configuración de pines:


Aquí está
Ahora para operación y programación necesitas conectarlo al programador según el diagrama:

Desafortunadamente, soy como un zapatero: sin botas, ahora no tengo un programador a mano, así que usaré Arduino UNO para cargar el firmware terminado en el microcontrolador y configurar los fusibles. Sólo necesitas descargar el boceto “Arduinoisp” de la carpeta de ejemplos del IDE de Arduino y conectarlo según el diagrama:


Sin embargo, esta solución tiene un inconveniente importante, del que hablaré un poco más adelante. Antes de comenzar a escribir un programa en CodeVisionAvr (en adelante, CvAvr), debemos decidir con qué frecuencia funcionará nuestro microcontrolador. Por defecto, de fábrica, nuestro héroe opera desde un generador rc interno a una frecuencia de 1 MHz (con la capacidad de reconfigurarse a 2, 4 y 8 MHz). Dado que el generador rc interno está calibrado en fábrica bajo ciertas condiciones (voltaje exacto, temperatura), la precisión de su funcionamiento en condiciones de "campo" puede diferir del 3% al 10%. Para tareas donde no se necesita una alta precisión de sincronización, esto se puede descuidar; en otros casos, es mejor usar cuarzo externo. En mi proyecto utilicé un cuarzo externo a una frecuencia de 8 MHz. Ahora necesitamos “explicarle” al MC que necesita trabajar con cuarzo externo. Esto se hace cambiando los fusibles. Para decirlo en términos simples, esto es algo así como una BIOS, como en una placa base, donde indicas sus modos de funcionamiento, de igual manera le decimos al MK en qué modos, además de la frecuencia, debe operar. Toda la información se almacenará en una memoria no volátil.
Te hablaré sobre cómo fusionar firmware debajo del spoiler; aquellos que sepan cómo hacerlo ellos mismos pueden desplazarse más.

información adicional

¿Cómo registrar estos mismos fusibles? Para ello utilicé el programa AvrDude, es gratuito y se puede encontrar fácilmente en Internet. Para configurar correctamente los fusibles de acuerdo con la frecuencia deseada, consulte la hoja de datos o puede utilizar una sencilla.
Configuramos los parámetros como en la imagen.


Aquí todo es sencillo:
Fuente de reloj: establece la frecuencia (cristal externo 3 - 16 Mhz) del cuarzo externo.
Tiempo de inicio: velocidad de inicio del MC después de quitar el RESET o aplicar energía (16K CK + 4,1 ms rápido).
Marque la casilla: Ext. Reloj/RC Osc./Baja frecuencia. Cristal: habilitar condensadores internos (36 pF)
Osc. R/C interno: ¡déjelo sin marcar! Cristal externo: habilitar el swing completo (necesario para >8 MHz).
Por lo tanto, obtuvimos Low Fuse 0xEF y High Fuse 0xC9. Genial, la mitad del trabajo hecho. Ahora conectamos el microcontrolador al Arduino UNO y el propio Arduino al ordenador, respectivamente. Inicie la línea de comando, vaya a la carpeta con AvrDude. Luego, ingrese la línea: avrdude -C avrdude.conf -c avrisp -P COM13 -b 19200 -p m8 -U lfuse:w:0xef:m -U hfuse:w:0xc9:m
Así es como se ve en la imagen:


Analicemos la línea que ingresaste:
avrisp es un tipo de nuestro programador tipo Arduino
COM13 es el número de puerto com que identifica nuestro Arduino en el sistema (en tu caso deberás buscarlo en el administrador de dispositivos)
19200 - velocidad del puerto com, dejar como está
m8 - indica que nuestro MK es Atmega8
-U lfuse:w:0xef:m -U hfuse:w:0xc9:m - nuestro fusible bajo 0xEF y nuestro fusible alto 0xC9 se indican aquí
Ser POR FAVOR CUIDADO!!, Un fusible especificado incorrectamente puede provocar que el MK se bloquee (no necesitamos bailar con una pandereta para restaurarlo).
Pulsamos “Enter” y en la salida obtenemos el resultado, como en la imagen:


Si no aparecen errores durante el proceso, entonces el trabajo está hecho, nuestro microcontrolador ahora funcionará desde cuarzo externo.
Puedes leer sobre fusibles con gran detalle y también buscando en Google.


Ahora estamos listos para comenzar a programar. Para mí, elegí el entorno de desarrollo CvAvr. El lenguaje de programación será diferente al de Arduino; en CvAvr es similar a C. Escribamos nuestro primer Blink.
Después de instalar e iniciar el entorno, utilizaremos el Asistente de creación de proyectos. Seleccione "Archivo" - "Nuevo" - "Proyecto". Cuando se nos pregunta si utilizaremos el asistente, respondemos afirmativamente. Tipo de chip AVR objetivo: AT90, ATtity, ATmega.
Así es como se ve el Asistente de proyectos:


En la pestaña Chip, seleccione ATmega8A, Reloj 8.000000 Mhz. Vaya a la pestaña Puertos. Nuestro LED se conectará al pin 14 del microcontrolador, según el pinout - PB0. En la pestaña, seleccione Puerto B, el bit 0 cambia de IN a OUT, es decir. Cambiamos el modo de funcionamiento de la pata 14 de nuestro microcontrolador a la salida.


Esto completa el trabajo del maestro. Seleccione "Programa" - "Generar, guardar y salir". Guardamos nuestro proyecto, por ejemplo, con el nombre Blink.

Consigamos una calza como esta.

/*******************************************************
Este programa fue creado por el
CodeWizardAVR V3.12 Avanzado
Generador automático de programas
Tipo de chip: ATmega8A
Tipo de programa: Aplicación
Frecuencia del reloj central AVR: 8,000000 MHz
Modelo de memoria: Pequeño
Tamaño de RAM externa: 0
Tamaño de la pila de datos: 256
*******************************************************/
#incluir
#incluir
// Declara tus variables globales aquí

Vacío principal (nulo)
{
// Declara tus variables locales aquí

// Inicialización de puertos de entrada/salida
// inicialización del puerto B
// Función: Bit7=Entrada Bit6=Entrada Bit5=Entrada Bit4=Entrada Bit3=Entrada Bit2=Entrada Bit1=Entrada Bit0=Salida
DDRB=(0<// Estado: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=0
PUERTO=(0<

// inicialización del puerto C
// Función: Bit6=En Bit5=En Bit4=En Bit3=En Bit2=En Bit1=En Bit0=En
DDRC=(0<// Estado: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PUERTO=(0<

// inicialización del puerto D
// Función: Bit7=En Bit6=En Bit5=En Bit4=En Bit3=En Bit2=En Bit1=En Bit0=En
DDRD=(0<// Estado: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PUERTO=(0<

// Inicialización del temporizador/contador 0

// Valor del reloj: Temporizador 0 detenido
TCCR0=(0<TCNT0=0x00;

// Inicialización del temporizador/contador 1
// Fuente del reloj: Reloj del sistema
// Valor del reloj: Temporizador1 detenido
// Modo: Normal arriba=0xFFFF
// Salida OC1A: Desconectada
// Salida OC1B: Desconectada
// Cancelador de ruido: desactivado
// Captura de entrada en flanco descendente
// Interrupción de desbordamiento del temporizador 1: desactivado
// Interrupción de captura de entrada: desactivada
// Comparar una interrupción de coincidencia: desactivada
// Interrupción de coincidencia de comparación B: desactivada
TCCR1A=(0<TCCR1B=(0<TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Inicialización del temporizador/contador 2
// Fuente del reloj: Reloj del sistema
// Valor del reloj: Temporizador2 detenido
// Modo: Normal superior=0xFF
// Salida OC2: Desconectada
ASSR=0<TCCR2=(0<TCNT2=0x00;
OCR2=0x00;

// Inicialización de temporizador(es)/contador(es) de interrupción(es)
TIMSK=(0<

// Inicialización de interrupciones externas
// INT0: Apagado
// INT1: Apagado
MCUCR=(0<

// inicialización USART
// USART deshabilitado
UCSRB=(0<

// Inicialización del comparador analógico
// Comparador analógico: apagado
// La entrada positiva del comparador analógico es
// conectado al pin AIN0
// La entrada negativa del comparador analógico es
// conectado al pin AIN1
ACSR=(1<SFIOR=(0<

//inicialización del ADC
//ADC deshabilitado
ADCSRA=(0<

// inicialización de SPI
// SPI deshabilitado
SPCR=(0<

// inicialización TWI
// TWI deshabilitado
TWCR=(0<

mientras (1)
{


No hay nada de qué preocuparse aquí; el proyecto especifica los modos de funcionamiento de puertos, temporizadores, interrupciones, USART, Comparador analógico, ADC, SPI y bibliotecas conectadas. En definitiva, todos los parámetros que especificamos en el asistente, todo menos los puertos y el chip, vienen configurados por defecto. Escribiremos el bucle principal del programa en while (1) (texto del programa). Porque Estamos trabajando con PB0 (14 tramos), en el bucle del programa escribiremos:
mientras (1)
{
PUERTO.0=1;
retraso_ms(1000);
PUERTO.0=0;
retraso_ms(1000);
}
Aquí configuramos PB0 alto, esperamos 1 segundo y lo configuramos bajo, luego el ciclo se repite. No olvides incluir la biblioteca al inicio del proyecto #include . ¡¡¡Nuestro programa está listo!!! Como puedes ver, todo es muy sencillo. Ahora seleccione "Proyecto" - "Construir todo". Si no se cometieron errores veremos el informe del asistente:

El tamaño de nuestro programa era de 198 bytes y ocupaba el 2,4% de la memoria de la micra.
A continuación montamos el diagrama:


Ahora vaya a la carpeta con nuestro proyecto, vaya a la carpeta "Depurar", luego a "Exe", hay un archivo con extensión hexadecimal. En mi caso es flash.hex.
Queda un último paso. Copie este archivo a la carpeta con AvrDude. Lanzamos nuevamente la línea de comando, vamos a nuestra carpeta. Ingrese la línea avrdude -C avrdude.conf -c avrisp -P COM13 -b 19200 -p m8 -U flash:w:blink.hex
Así es como se ve en la imagen:


Si todo está ingresado correctamente, presione “Enter”


¡Felicidades! El trabajo está hecho, el LED debería parpadear felizmente :)
Conclusión.
En conclusión, quiero decir sobre la desventaja del programador tipo Arduino: CvAvr simplemente no lo admite. Teniendo, por ejemplo, AVRISP mkII en la mano, puede flashear los fusibles y descargar el programa directamente desde CodeVisionAvr. Por cierto, el programador casero también se negó a utilizar la interfaz gráfica de AvrDude y trabajó únicamente desde la línea de comandos.
Descubrí CodeVisionAvr bastante rápido; Internet está lleno de lecciones en texto y video. En un par de semanas dominé el funcionamiento del hardware PWM, interrupciones, temporizadores, trabajo con botones y conexión de una pantalla gráfica. Específicamente, tuve que hacer parte de mi proyecto: organizar un hardware PWM de 16 bits en el Atmega8, conectar 2 botones para controlarlo y también mostrar sus modos de funcionamiento en una pantalla gráfica, lo cual hice con facilidad :) Aquí hay un par de fotos:

información adicional





Resultados en comparación con Arduino:
+ Comprender el CvArv no es difícil porque hay un asistente para la creación de proyectos;
+ Disponibilidad de bibliotecas de complementos, hay suficientes;
+ Compilación rápida;
+ La capacidad de simular un proyecto en Proteus, así como depurarlo usando el depurador incorporado;
+ El tamaño del programa es varias veces menor. Standard Blink nos llevó 198 Bytes, un boceto similar en Arduino IDE 1084 Bytes + 2 KB de gestor de arranque;
+ Capacidad para implementar modos que no se pueden realizar en Arduino. Por ejemplo, PWM de 16 bits (en general, es posible en Arduino, pero sólo con “muletas”);
+ La capacidad de utilizar microcontroladores ATtiny y ATmega para sus proyectos en los que Arduino sería redundante;
- Aún así, es mejor que un principiante empiece a dominar MK con Arduino;
- El lenguaje de programación es diferente al procesamiento de Arduino;
- Todavía hay más bibliotecas para Arduino;
- CodeVisionAvr es un programa pago, existen versiones gratuitas con limitaciones;
Al programar el microcontrolador "desnudo" en CodeVisionAvr, adquirí mucha experiencia. Estudiar temporizadores, registros, modos de funcionamiento, arquitectura y leer hojas de datos aumentará sus habilidades, ampliará sus horizontes y abrirá nuevos aspectos del trabajo con microcontroladores.
Como beneficio adicional, adjunto un par de fotos cuando descubrí la pantalla LCD gráfica y jugué un poco.





PD. Hay muchas más cosas sobre las que quería escribir, pero esto no será una reseña, sino un artículo extenso. Estoy dispuesto a responder preguntas de mi competencia, en privado o en comentarios. Puedes ver muchas lecciones sobre AVR.

Arriba