En mi
primer artículo, hablé sobre esta familia de controladores; más de una docena de personas me escribieron en PM con preguntas al respecto, aunque este no era el tema del artículo. La gente categóricamente no quería ir a Google, hablando de la falta de información. Me sorprendió un poco y decidí verificarlo; de hecho, en ruso, prácticamente no hay nada en la familia C2000 (en el contexto de AVR, STM), y lo más importante es que no hay guías de inicio claras. La información se puede encontrar en inglés, pero nuevamente no es suficiente. Para mí, esto es algo sorprendente, dado que esta familia no tiene pocos años. Por lo tanto, se decidió lo mejor que pudieron para influir en la situación.
¿Quién necesita estos controladores en principio ... ¿Desea ensamblar un inversor de soldadura? Fuente de alimentación ininterrumpida? Plancha de baño de galvanoplastia? Frecuencia? ¿Un inversor para energías alternativas? Máquina CNC? Si al menos un punto es sobre ti, ¡entonces el artículo está dedicado a ti!
Otros lectores también estarán interesados en aprender sobre el controlador "nuevo-viejo", por qué es necesario y cómo trabajar con él. Esta familia es muy simple (mucho más simple que STM, LPC y otros Cortex), las piedras son fáciles de comprar (también hay Ali), le permiten implementar soluciones industriales altamente confiables, sobre la base de que puede construir casi cualquier sistema de control industrial.
¿Ya has decidido que este controlador es tu sueño y estás listo para la batalla? Luego compramos por $ 17 la siguiente depuración de F28027-LaunchPad:
Has comprado Ahora puedes ir a la batalla. Si surgió la pregunta de dónde comprar "mejor" y "más barato", entonces vamos a la tienda oficial. Vamos
aquí y vemos el precio de $ 17. Por este monto, recibirá una tarifa de depuración original y la entrega de mensajería a la puerta. Pedí una vez en China para la entrega, resultó $ 16 y es con un descuento y un cupón, así como un viaje de "bonificación" a la oficina de correos. Por lo tanto, recomiendo que sea el oficial. Vamos!
Descripción general de la serie C2000
Puede leer más detalladamente sobre todo en el
sitio web oficial , por supuesto, en inglés. Hablaré brevemente al respecto y expresaré mis pensamientos sobre la aplicación. Tenga en cuenta que esto es solo mi especulación y no afirman la verdad.
Primero, algunas palabras sobre el C2000 en general. Las características distintivas de la familia, que están asociadas con su propósito principal de control motor, son la presencia de HRPWM (PWM de alta precisión) y CLA (coprocesador). Este último está realmente ausente en el Piccolo TMS320F2802x más joven, pero no es necesario allí, lo principal es HRPWM en su lugar. Qué es ... HRPWM en sí es un PWM normal, solo es muy preciso y el tiempo de grabación y configuración para un nuevo ciclo de trabajo es significativamente más rápido. Esto permite obtener, por ejemplo, un seno perfectamente formado en un inversor CC / CA o controlar motores paso a paso en una máquina CNC con una precisión muy alta.
El CLA es esencialmente un núcleo completo, pero no tiene acceso a periféricos, solo al núcleo principal y la memoria. Sirve para descargar el núcleo principal de la informática. Este coprocesador digiere muy fácilmente y naturalmente los datos flotantes, lo cual es importante al implementar varios algoritmos, filtros y más.

Hablaré sobre dos familias principales que probablemente encontrarás:
- Piccolo Los controladores más jóvenes, pero también los más baratos. Mi TMS320F28027 es de esta familia. Si decide desarrollar electrónica de potencia para fines comerciales, estas serán sus piedras principales: son bastante baratas, pagaderas (LQFP, QFN, TSSOP) y le permiten implementar casi todo. Por ejemplo, su rendimiento es suficiente para un PFC bifásico, un inversor para paneles solares, un convertidor de frecuencia de hasta 10 kW con control vectorial, etc. Como puede ver, este es un segmento de productos que es comprado por personas y empresas comunes, lo que significa que tiene una gran demanda. Las principales limitaciones son la frecuencia de 60 MHz, un número limitado de canales PWM.
- Delfino Ideológicamente, todos son el mismo Piccolo, solo inflados con meldonium. En lo que se expresa: una frecuencia de hasta 200 MHz, en piedras antiguas ya hay 2 núcleos completos + 2 coprocesadores, cajas grandes y, en consecuencia, muchas patas, muchos canales PWM, muchos ADC y, en general, muchos. Es decir, en piedras más antiguas tenemos 4 núcleos con una frecuencia de 200 MHz, un rendimiento de 800 MIPS, que es bastante impresionante. Dicha potencia se puede utilizar de diferentes maneras, pero la aplicación principal son los sistemas algorítmicamente complejos, por ejemplo, el rectificador de Vienne u otra cosa. También en uno de estos controladores, puede implementar todo el sistema de control para una máquina CNC, por ejemplo, fresado o corte por llama de metal.
Finalización del tablero de depuración
Cuando reciba una caja con una placa de depuración, encontrará el cuarzo y los condensadores que faltan. No son necesarios, pero es aconsejable doparse. Ya no tengo cuarzo en el HC-49, así que tuve que pedirlo prestado a un amigo. Elige AVR y STM, por lo que solo encontró 8 MHz. Soldado Agregué 22 condensadores pF de la memoria anterior, como lo hice en mega en la escuela.
Esta solución no es la mejor y está conectada con la configuración PLL. El multiplicador máximo para PLL es x12 (más puede ser, pero no se recomienda, y funciona de forma torcida). La frecuencia máxima es de 60 MHz. El valor máximo del divisor en la salida PLL es 3. La frecuencia del cuarzo es de 8 MHz. No puedo multiplicar por 8 por un número entero y obtener 60. Estamos buscando el valor total más cercano, en este caso 240. Es decir, multiplico 8 por 30, y luego dividiendo por 4 obtengo el codiciado 60 MHz, pero el problema es que el multiplicador PLL x30 es inaceptable , divisor / 4 tampoco está disponible. Hay 2 salidas:
- Malo: multiplique la frecuencia de 8 MHz por 7 y divida por 1 y obtenga 56 MHz. Puede multiplicar por 8 y obtener 64 MHz, funcionará de manera estable, pero en ambos casos la frecuencia no es máxima de 60 MHz. No hay suficiente perfeccionismo, por desgracia. Tengo una opción así, soldaron 8 MHz e hice una frecuencia de 56 MHz.
- Bien: vaya y compre cuarzo a 10 o 20 MHz (mejor que 10) y multiplique por 6, bueno, divida por 1, obtenemos los apreciados 60 MHz. Vivo fuera de la ciudad y, sinceramente, era demasiado vago para ir a una tienda local, lo que no es el hecho de que haya cuarzo de 10 MHz. Por supuesto, el circuito RC interno y el cuarzo de 8 MHz se usarán para la capacitación, pero en sus proyectos futuros, coloque el cuarzo de 10 MHz, no los mutantes gigantes en el paquete HC-49.
Arquitectura y características periféricas.
Todo lo que sucederá a continuación se aplica al controlador TMS320F28027. Para comenzar, veamos la estructura que se toma de la
hoja de datos :

Lo primero a lo que debe prestar atención es que la RAM se divide en 3 sectores: M0, M1 y SARAM. Los volúmenes de estos sectores de memoria en nuestro caso son 1k, 1k y 4k. Vale la pena señalar que en este caso la palabra no es de 8 bits, sino de 16 bits, es decir, en una forma más familiar, es 2 kB + 2 kB + 8 kB. La peculiaridad de este módulo es que los sectores M0 y M1 son más rápidos que los 8 kB restantes de RAM. Formalmente, puedes tomar esto como caché. Los sectores M0 y M1 generalmente almacenan los datos más utilizados, así como los datos que son más críticos para el rendimiento de la memoria. De manera predeterminada, podemos usar el vinculador para especificar qué y dónde se almacena, pero no mencionaré este tema en este artículo, aquí al menos se necesita un artículo separado.
La segunda característica importante es que todos los periféricos se sincronizan desde el bus del sistema, es decir, desde 60 MHz (en mi caso, 56 MHz). Como ejemplo, daré los microcontroladores STM32, donde la frecuencia central es, por ejemplo, 180 MHz para F4, pero los periféricos se sincronizan a través de una serie de divisores. Yo llamo a este enfoque "megahercios falsos" para mí, aunque esto es muy exagerado. Por lo tanto, 60 MHz para TMS320F28 y 180 MHz para stm32 no son tan diferentes, y si recuerda la presencia de CLA, 60 + 60 MHz son al menos comparables. Está claro que tal comparación no es correcta, pero deja claro que no solo los megahercios están hartos.
También un punto interesante: preste atención a la estructura general: HRPWM, ADC, comparadores con un DAC interno, módulo de procesamiento del codificador (eCAP) ... ¡Un convertidor de frecuencia listo para usar con control vectorial en su forma pura! Esta es toda la esencia de esta familia: el minimalismo. Por un lado, la periferia es bastante pobre en comparación con Cortex, pero por otro lado, es suficiente para implementar una respuesta de frecuencia, dc / dc, dc / ac y un controlador de motor paso a paso. Debido a esto, trabajar con los controladores TMS320F28 es muy simple, comprensible y no está sobrecargado con acciones innecesarias. Pero si de repente necesita 3 UART, y para ellos un par de i2c y 3 SPI más, entonces estos controladores definitivamente no son para usted, tienen diferentes tareas.
Ambiente de desarrollo
¿Has mirado el logo de splash? Recuérdala Si decide comenzar a usar artículos en el desarrollo de los héroes del artículo, entonces este software es todo suyo y, como puede ver, el
software se
llama controlSUITE .
Esta aplicación es una colección y biblioteca de todo lo que necesita para desarrollar software para la familia de controladores C2000. Instalar esta aplicación es lo primero que debe hacer y ver su composición, contiene:
- Descripción de todos los controladores y tableros de depuración existentes basados en ellos. Fuentes de circuitos, placas de circuito impreso, listas de materiales principalmente en Altium Designer
- Ejemplos de circuitos y diseño de placas de circuito impreso.
- Bibliotecas principales para el desarrollo de firmware
- Bibliotecas de matemáticas y DSP, incluso para usar con CLA
- Un ejemplo de proyectos de software para cada tipo de periférico.
- Una gran cantidad de apnouts para la implementación de la mayoría de los algoritmos para controlar motores, convertidores dc / dc, controladores MPPT y otros sistemas
- Un conjunto de programas que le permiten crear un sistema de gestión del motor sin necesidad de programar, simplemente usando un entorno gráfico
- El propio IDE, que se desarrollará
Todo lo que describí anteriormente es muy breve y modesto. Le llevará un par de semanas ver y desplazarse al menos en diagonal. Por supuesto, no necesitará la mayor parte de esta cantidad de datos al principio, pero debe recordar a dónde ir si algo le resulta incomprensible y extravagante.
Ahora con lo que trabajaremos hoy es con el IDE, cuya parte gráfica se basa en el conocido Eclipse. El compilador no es GCC, pero es propio de Texas, que en mi opinión subjetiva es definitivamente mejor que el primero. Aunque hay sospechas de que esto está completamente dopado de la misma manera. El entorno de desarrollo se llama
Code Composer Studio , la versión actual 7.4.
Creación de proyectos
Al principio, quería implementar una tarea idéntica al primer artículo, es decir, dibujar un seno. En principio, en el marco de un artículo, esto podría haberse hecho dejando un marco de un volumen muy grande de cosas pequeñas, pero como saben, la esencia está precisamente en las cosas pequeñas. Hay varios artículos sobre TMS en Internet, pero todos son muy superficiales y se reducen al tipo de "copia esto y todo funciona", es decir, el proceso en sí y la ideología no se consideran en absoluto. Por lo tanto, en el marco de este artículo, crearemos un proyecto, lo limpiaremos de componentes innecesarios, configuraremos el firmware en la memoria flash del controlador y aprenderemos cómo trabajar con GPIO, y aquí son muy interesantes.
Descargue CCS7 del sitio web del fabricante, instale y comience a crear el proyecto de la manera habitual:
Archivo → Nuevo → Proyecto CCS ...Vemos esta ventana y en ella debemos seleccionar el controlador que nos interesa, en mi caso es TMS320F28027, indicar el nombre del proyecto y prescribir la ruta donde se almacenará. Primero debe crear una carpeta donde se almacenará el proyecto. El nombre del proyecto y el nombre de la carpeta pueden no coincidir. Haga clic en el botón
Finalizar y se creará nuestro proyecto.
Ahora necesita llenar nuestro proyecto con contenido y conectarlo. Antes de eso, para mejorar la estructura del proyecto, cree este conjunto de carpetas:
- inc : una carpeta que contiene todos los archivos de encabezado
- system_inc : esta sección almacenará los archivos de encabezado de las bibliotecas estándar, los archivos que nosotros mismos crearemos, por ejemplo, main.c están en la carpeta inc. Esto no romperá algo sin pensar o eliminará innecesariamente
- src - carpeta con todas las fuentes
- system_src : carpeta con archivos de origen para bibliotecas estándar
Tenga en cuenta que esta estructura no es una especie de dogma, sino que es solo mi idea de ordenar. Aunque lo recomendaré a personas con experiencia mínima, con el tiempo lo cambiarás para que se ajuste a tu visión del mundo, pero por ahora esto minimizará la cantidad de jambas.
Ahora cree el archivo main.h en la carpeta inc y conéctelo a main.c. A través de él se conectarán las bibliotecas base. Y antes de comenzar a transferir bibliotecas y otros archivos, escriba la ruta a las carpetas donde se guardarán nuestros futuros archivos de encabezado en la configuración del proyecto. Para hacer esto, haga clic derecho en el proyecto (Prueba) en el árbol del proyecto y haga clic en
Propiedades en la parte inferior o simplemente presione
Alt + Entrar . En la ventana que se abre, vaya a
Compilar → Compilador C2000 → Incluir opciones y aquí necesitamos dos rutas existentes: registre la ruta a las carpetas inc y system_inc. Haga clic en
Agregar , luego en
Espacio de trabajo y luego en la carpeta inc deseada, luego haga lo mismo y agárrese a la segunda carpeta. Por lo tanto, prescribimos rutas relativas; al transferir un proyecto, no tendrá que volver a configurar nada. Como resultado, obtenemos esa imagen y hacemos clic en
Aceptar :

Ahora tenemos un proyecto vacío con las rutas prescritas y otras configuraciones, solo queda llenarlo con bibliotecas. Lo único que debe hacer es verificar si todo está conectado. En teoría, debe obtener dicho código y una imagen, compilar el proyecto. Para hacer esto, presione
CTRL + B o vaya a
Proyecto → Construir todo en la parte superior. El proyecto debe compilarse sin errores y tener este aspecto (se puede hacer clic en la imagen):

Ahora hablemos un poco sobre el enlazador. Inicialmente, al crear un proyecto, el IDE genera el archivo
28027_RAM_lnk.cmd , coloca nuestro programa en la RAM durante la depuración y el firmware. Esto es conveniente cuando estamos depurando, porque Los recursos de memoria flash no se desperdician y el ingreso de depuración en RAM es significativamente más rápido. Pero, ¿y si queremos coser en flash? Para hacer esto, hay otro archivo de enlace que colocará nuestro programa en flash. Mostraré esta opción.
En primer lugar, elimine el archivo
28027_RAM_lnk.cmd . Como dije,
controlSUITE es nuestro todo. Lo abrimos Ahora vaya en
inglés → Dispositivo → Piccolo F2802x → Bibliotecas compatibles → Archivos de encabezado para F28027x . A la derecha vemos carpetas: estas son las bibliotecas estándar y todo lo que se necesita, incluidos los vinculadores. Ahora vamos a la carpeta
f2802x_common → cmd y aquí vemos un conjunto de enlazadores para todas las piedras en la línea. No es difícil adivinar los archivos _RAM para cargar el código en la RAM, y sin esta etiqueta para cargar mediante flash. Tomamos el archivo
F28027.cmd y lo copiamos a nuestro proyecto en lugar del antiguo vinculador remoto.
Ahora es el momento de migrar las bibliotecas ellos mismos. Vamos a la carpeta
f2802x_common → source y vemos un montón de archivos. Hay dos tipos de bibliotecas: registros estándar (similares a CMSIS) y algún tipo de SPL. En este caso, solo nos interesa la primera vista, es decir, los archivos con el prefijo
f2802x_ . Por supuesto, puede arrastrarlos todos a nuestro proyecto, pero ¿por qué obstruirlo si no usamos todo? Si necesita algo, en el futuro solo lo agregaremos. Por ahora, nos restringimos a los siguientes conjuntos de archivos:
- f2802x_codestartbranch.asm
- f2802x_defaultisr.c
- f2802x_piectrl.c
- f2802x_pievect.c
- f2802x_sysctrl.c
Copiamos el archivo de datos y lo
pegamos en nuestra carpeta
system_src . Ahora vamos a la carpeta
f2802x_headers → source y tomamos el archivo
F2802x_GlobalVariableDefs.c desde allí y lo copiamos nuevamente a nuestra carpeta
system_src . A continuación, vaya a la carpeta
f2802x_headers → cmd y copie el archivo
F2802x_Headers_nonBIOS.cmd desde allí a la misma carpeta. Esto completa el llenado de la carpeta
system_src y continúa con los encabezados.
Vamos a la carpeta
f2802x_headers → incluimos y copiamos todos los archivos desde allí a nuestra carpeta
system_inc . Ahora vamos a la carpeta
f2802x_common → fuente y copiamos los archivos desde allí:
- f2802x_examples.h
- f2802x_globalprototypes.h
- f2802x_i2c_defines.h
- f2802x_epwm_defines
- f2802x_swprioritizedisrlevels.h
- f2802x_defaultisr.h
Deberíamos obtener esta imagen en el árbol del proyecto:
Ahora necesita conectar las bibliotecas básicas, el archivo
main.h toma la siguiente forma:
#pragma once #include "F2802x_Device.h" #include "F2802x_examples.h"
Estamos intentando compilar. Si el proyecto se compiló sin errores y advertencias, entonces todo está conectado correctamente. Si esto no sucedió, verifique las 10 veces, y si no funciona, escriba al Primer Ministro.
Ayudaré , como Owl dijo:
"Baz-woz-mEz-bottom, es decir, para nada" .
Inicialización del controlador y sistema de reloj.
En esta sección, escribiremos una función que inicializa el temporizador de vigilancia y los vectores de interrupción, y establece los indicadores de interrupción en cero. También configuramos el sistema de reloj, como resultado de lo cual el cuarzo externo en lugar de la cadena RC interna se convertirá en la fuente del reloj, configurará el PLL y habilitará el reloj para todos los periféricos.
Para la precisión del código, propongo poner todas las inicializaciones básicas en un archivo separado, cuya interfaz será la función
void InitStartSystem (void) . Para hacer esto, cree los archivos
systemInitStart.h y
systemInitStart.c . Inmediatamente escribiré una función y luego simplemente analizaremos su contenido:
void InitStartSystem (void) { DisableDog(); XtalOscSel(); InitPll(TMS320_PLLCR, TMS320_DIVSEL); InitPeripheralClocks(); InitPieCtrl(); InitPieVectTable(); }
Todas las funciones que se llaman en
InitStartSystem () son estándar. Le aconsejo que vea en detalle cómo se implementan, para esto puede mantener presionada la tecla CTRL y hacer clic en la función de interés. Has mirado? Ahora ve brevemente ...
- DisableDog () : la función apaga el "perro". Este es un paso obligatorio cuando se configura la parte principal de periféricos críticos, por ejemplo, un sistema de reloj. En el código de la biblioteca a menudo se ve esto, se duplicará y duplicará
- XtalOscSel () : esta función implementa el cambio de una fuente de reloj interna a un cuarzo externo. Un punto importante! Hay un error en la biblioteca estándar con esta función: no se declara. Vamos al archivo f2802x_globalprototypes.h y, entre todos los demás, agregamos la línea extern void XtalOscSel (void)

El segundo punto importante! Vaya a la función XtalOscSel y elimine la función de retraso.

El tercer punto importante! Vamos al archivo f28027x_exmaples.h y comentamos la función de implementación de retraso.

- InitPll (TMS320_PLLMUL, TMS320_DIVSEL) : la función configura el PLL. Se le transfieren 2 valores: multiplicador y divisor. Su valor se especifica en el archivo de encabezado. Un punto importante! Abrimos esta función en la biblioteca y necesita comentar el retraso en la parte inferior

- InitPll (TMS320_PLLMUL, TMS320_DIVSEL) : la función configura el PLL. Se le transfieren 2 valores: multiplicador y divisor. Su valor se especifica en el archivo de encabezado. Un punto importante! Abrimos esta función en la biblioteca y necesita comentar el retraso en la parte inferior
- InitPeripheralClocks () : esta función simplemente habilita el reloj para toda la periferia. Si para todos. C2000 no es una solución para glándulas alimentadas por batería,
esta solución de unidades decenas de cientos de kilovatios y patético 2-3 mA no jugará un papel aquí. Bueno, no tienes que recordar cada vez que enciendes el reloj para algún tipo de SPI o no - InitPieCtrl () : la función apaga todas las interrupciones y restablece los indicadores de interrupción
- InitPieVectTable () : la función llena la tabla con vectores de interrupción
En realidad, aquí está todo inicialización. Creo que muchos han notado los "puntos importantes" asociados con la función
Delay . ¿Por qué lo cortamos en la vid? Sí, todo es simple: es una muleta.
Los ingenieros de TI agregaron estos retrasos completamente innecesarios a algunas de las funciones, agregadas en actualizaciones recientes. Por qué, un misterio no solo para mí. Los registros y otras entradas críticas ya están protegidos, por lo que no hará que nuestro controlador sea estúpido. Por cierto, cuando se inicializa en electrónica de potencia, es imposible "contundente", de lo contrario serán mariquitas. Por lo tanto, ¡olvide las funciones de
retraso y otra diabólica para siempre, solo temporizadores! Los retrasos son permitidos solo para algunos fines educativos, por ejemplo, parpadear rápidamente con un LED.
Para verificar que el código funciona, llamamos a la función de inicialización en main, compilar, flashear y
conectar al osciloscopio
GPIO18 . Este pin es similar al MCO del STM32, lo que significa que emite la frecuencia del sistema. Un osciloscopio debería ver una señal con una frecuencia de 56 MHz. Si el osciloscopio es bueno, verá el meandro, si es chino (incluso bueno), lo más probable es que sea algo más cercano al seno. La configuración de GPIO18 para emitir la frecuencia del sistema se puede ver en la función
InitPeripheralClocks () . Primero necesita "conectar" gpio a la salida de frecuencia, y luego configurar el divisor en 1:
GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 3;
Configuración GPIO
Para trabajar con esta familia, solo necesitamos un manual de referencia, que los desarrolladores de TI han dividido en varios archivos, cada uno de los cuales describe una cierta periferia, lo cual es muy conveniente. Descargue la hoja de datos
aquí y vaya a la sección
Soporte de documentación en la página 126. Aquí vemos un conjunto de enlaces a la documentación con su breve descripción: erratas, una guía para iniciar la gestión del motor y guías en cada periferia. Estamos interesados en un documento llamado
TMS320F2802x / TMS320F2802xx Piccolo System Control and Interrupts Guide , contiene la descripción del GPIO y otras configuraciones básicas del sistema que nos interesan. Nos fijamos en el diagrama de bloques GPIO:

Vemos una imagen bastante familiar de los puertos de entrada / salida del dispositivo. Aquí y la capacidad de encender el tirante interno, y el uso de una señal con GPIO para interrupciones y otras delicias. La característica principal de este periférico en el C2000 es la posibilidad de supresión de interferencia de hardware, por ejemplo, el ruido de los contactos mecánicos de un botón. Veamos un diagrama interesante:

Muestra el principio de leer el estado de las entradas. En la mayoría de los controladores, el estado de entrada se lee con la frecuencia de reloj de esta periferia, es decir, por defecto con una frecuencia de 56 MHz en nuestro caso, y para el mismo stm en las familias más antiguas, estas frecuencias son aún más altas. Creo que todos entienden que a esa frecuencia el controlador tiene tiempo para "ver" cualquier interferencia y ruido. Algunas veces se necesita dicha frecuencia, y otras no, por ejemplo, si necesitamos sondear un botón. ¿Por qué la entrevistaríamos cada 18 ns? Por lo tanto, nos dimos cuenta de la posibilidad de reducir la frecuencia de reloj de un puerto específico usando el registro
CTRL y los bits
QUALPRDx , donde X toma un valor de 0 a 3: QUALPRD0 es responsable de GPIO0 ... 7, QUALPRD1 es responsable de GPIO8 ... 15 y así sucesivamente. De hecho, este es un divisor de frecuencia ordinario con un coeficiente de 1 a 510.

A menudo no tiene sentido interrogar un botón, por lo que ajustaremos el divisor a 510, es decir, al máximo. Volvemos a mirar el diagrama y vemos que la señal se considera estable solo cuando su nivel no cambió durante 6 ticks. El número de medidas necesarias para la fijación puede ser 1, 3 o 6.
Cuanto más grande sea el divisor y cuantos más ciclos arreglemos, más estable será
la protección contra el parloteo. Cuando hay una charla de contactos, al principio serán transiciones caóticas de 0 a 1 y viceversa, cuando la charla pasa y la señal se detiene y no cambia durante 6 relojes, esto significa que se presiona el botón. Todo lo ingenioso es simple.
Ahora echemos un vistazo a los registros principales, no tocaremos las interrupciones, solo la configuración de los puertos. Primero debe decir que los registros se dividen en 2 tipos:
registros de configuración y
registros de datos . Los primeros son responsables de la configuración de las propiedades, por ejemplo, esta entrada o salida. El segundo grupo es responsable de escribir y leer el estado del puerto.
Registros de configuración:- GPxCTRL : regístrese para escribir el divisor del reloj. En lugar de "x", sustituimos la letra "A" - si tenemos GPIO0 ... 31, "B" - si usamos GPIO32 ... 63 y así sucesivamente
- GPAQSELx : regístrese para establecer el número de ticks para fijar el valor en la entrada
- GPAMUX1 es un registro para seleccionar periféricos conectados, por ejemplo, indica que GPIO o UART, o tal vez PWM, se ponen de pie.
- GPADIR - Registro de selección de dirección GPIO: entrada o salida. Por defecto, todos los puertos están configurados para entrada.
- GPAPUD es el registro responsable de conectar el suspensor interno a VCC.
Vale la pena señalar que, para algunos puertos, de forma predeterminada, el pull-up está desactivado y, en parte, está activado.
¡Es importante recordar esto!
Registros de datos:- GPADAT - registro de estado de salida. Si la salida está configurada para entrada, entonces leemos el estado de entrada. Si está configurado para una salida, entonces podemos anotar el valor que debe tomar esta salida, es decir, 0 o 1
- GPASET - registro configurando la salida a "1". Para establecer en "1", debe escribir "1", al escribir "0" se ignora el comando
- GPACLEAR - registro configurando la salida a "0". Para establecer en "0", debe escribir "1", al escribir "0" se ignora el comando
- GPATOGGLE es un registro que invierte el valor actual del estado de salida. Para invertir el valor, escriba "1"; al escribir "0", se ignora el comando
Aquí hay un conjunto tan simple de registros. Incluso a partir de la descripción anterior, ya puede comprender lo que debe hacerse para configurar el puerto, pero los ingenieros prudentes o los escritores técnicos de TI hicieron otra instrucción paso a paso:

Diré de inmediato que los pasos 6 y 7 no son necesarios para nosotros, porque ni el perro ni la interrupción se usan en este artículo. Describiré brevemente los pasos restantes para las personas que estudiaron alemán en la escuela:
- Paso 1 : determine la funcionalidad de salida: que será una entrada o salida,
gpio o salida a otros periféricos y cosas - Paso 2 : habilite o deshabilite el pull-up interno
- Paso 3 : configure la protección de sincronización y rebote para un puerto específico
- Paso 4 - selecciona la función deseada: gpio o periféricos
- Paso 5 - establece la dirección de salida: entrada o salida
Esa es toda la configuración, como puede ver, es elemental y lógicamente clara. Quiero señalar de inmediato que no es necesario en este orden realizar ajustes, por ejemplo, puede establecer la dirección (entrada o salida) desde el primer paso. No importa
Super importante!Al trabajar con registros de la familia C2000, es necesario tener en cuenta el momento en que están protegidos. Todo lo que se describe a continuación se aplica principalmente a los registros del grupo de configuración. Si observaba cuidadosamente las funciones estándar, probablemente vio comandos extraños allí:
EALLOW; y
EDIS; . Comando
EALLOW : elimina la protección y proporciona acceso para trabajar con registros del sistema. Comando
EDIS : habilita la protección de la espalda y proporciona acceso para trabajar con registros del sistema. Es decir, cualquier trabajo con registros del sistema SIEMPRE debería verse así:
EALLOW;
Tal operación no es necesaria si trabajamos con registros de datos, por ejemplo, si configuramos nuestra salida a "1" usando el registro
GPxSET , entonces no necesitamos quitarle protección y, en consecuencia, volver a encenderla. La documentación en todas partes dice lo que debe protegerse y lo que no es, por ejemplo, así:

Basado en todo lo anterior, configuremos GPIO0 ... 3 con LED para la salida. Sugiero colocar todos los ajustes de GPIO en la función
InitLEDgpio y escribirlo:
void InitLEDgpio (void) { EALLOW; GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; GpioCtrlRegs.GPADIR.bit.GPIO1 = 1; GpioCtrlRegs.GPADIR.bit.GPIO2 = 1; GpioCtrlRegs.GPADIR.bit.GPIO3 = 1; EDIS; }
Por defecto, nuestros GPIO ya están configurados como GPIO, como todos los valores de registro se borran, lo que significa que "0" ya está escrito en el registro GPAMUX1. Para GPIO0 ... 11, el pull-up está deshabilitado de manera predeterminada, por lo que solo podemos tomar y determinar la dirección del trabajo hacia la salida usando GPADIR. Si recuerda, los LED están conectados al controlador por cátodos, lo que significa que inmediatamente después de la inicialización se encenderán. Establezcamos estas conclusiones directamente en la función de inicialización en "1":
void InitLEDgpio (void) { EALLOW; GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; GpioCtrlRegs.GPADIR.bit.GPIO1 = 1; GpioCtrlRegs.GPADIR.bit.GPIO2 = 1; GpioCtrlRegs.GPADIR.bit.GPIO3 = 1; EDIS; GpioDataRegs.GPASET.bit.GPIO0 = 1; GpioDataRegs.GPASET.bit.GPIO1 = 1; GpioDataRegs.GPASET.bit.GPIO2 = 1; GpioDataRegs.GPASET.bit.GPIO3 = 1; }
Como puede ver, no uso el registro
GPADAT para escribir, pero uso
SET, CLEAR, TOGGLE . También tenga en cuenta que hice esta entrada fuera de la zona protegida, es decir, después del comando
EDIS . Ahora, en la misma función, configure GPIO12 para que funcione con el botón y agregue nuestra función:
void InitLEDgpio (void) { EALLOW; GpioCtrlRegs.GPADIR.bit.GPIO0 = 1; GpioCtrlRegs.GPADIR.bit.GPIO1 = 1; GpioCtrlRegs.GPADIR.bit.GPIO2 = 1; GpioCtrlRegs.GPADIR.bit.GPIO3 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO12 = 1; GpioCtrlRegs.GPACTRL.bit.QUALPRD1 = 0xFF; GpioCtrlRegs.GPAQSEL1.bit.GPIO12 = 2; EDIS; GpioDataRegs.GPASET.bit.GPIO0 = 1; GpioDataRegs.GPASET.bit.GPIO1 = 1; GpioDataRegs.GPASET.bit.GPIO2 = 1; GpioDataRegs.GPASET.bit.GPIO3 = 1; }
En primer lugar,
apago el ajuste interno escribiendo "1" en el registro
GPAPUD , porque GPIO12 lo habilita de forma predeterminada. Como escribí anteriormente, todos los puertos después de la inicialización están configurados para entrada, como los ceros están escritos en el registro
GPADIR , no lo configuramos aquí.
Queda por configurar la protección contra el rebote, para esto dividimos los divisores
0xFF , que corresponde al valor / 510. En el registro
GPAQSEL1 escribimos el valor "10" o 2, que establece el valor en una muestra de 6 medidas. Hecho Para leer el valor de una entrada específica, solo necesita leer el valor del registro
GPADAT :
if (GpioDataRegs.GPADAT.bit.GPIO12) {
Así es como interrogamos las conclusiones necesarias. Ahora llamemos a la función de configuración gpio en nuestra función principal y obtengamos su forma final:
void InitStartSystem (void) { DisableDog(); XtalOscSel(); InitPll(TMS320_PLLMUL, TMS320_DIVSEL); InitPeripheralClocks(); InitPieCtrl(); InitPieVectTable(); InitLEDgpio(); }
Ahora llamamos a la función
InitStartSystem en el cuerpo principal del programa en main y esto completa la configuración. Obtenemos el siguiente código:
#include "main.h" int main (void) { InitStartSystem(); while(1) { } }
Es hora de escribir nuestro primer programa de prueba y probar todo esto. El algoritmo es este: el LED que se encuentra en GPIO3 parpadea, y cuando presiona el botón en GPIO12, simplemente iluminamos el LED GPIO0. Por lo tanto, verificaremos el funcionamiento de los puertos para entrada y salida. Escribimos el siguiente código:
#include "main.h" int main (void) { InitStartSystem(); while(1) { if (GpioDataRegs.GPADAT.bit.GPIO12) { GpioDataRegs.GPACLEAR.bit.GPIO0 = 1; } else { GpioDataRegs.GPASET.bit.GPIO0 = 1; } GpioDataRegs.GPATOGGLE.bit.GPIO3 = 1; delay(100000); } }
Compilamos, vamos al depurador, lo iniciamos y vemos cómo un LED parpadea constantemente, y cuando presiona el botón, se ilumina otro. Al final de la sección adjuntaré un proyecto con este código, si algo no funciona, investigue. Especialmente para aquellos que tienen problemas con los mensajes de texto o que no han entendido todos los puntos, sugiero que vean este video sobre cómo trabajar con GPIO, todo está sucediendo allí, como en la sección "GPIO". Te advierto que el video durante una hora, triste, largo, pero lo más detallado posible y todo es visible:
Archivos del artículo
- Archivo con el proyecto para descargar CCS7 aquí
- Puedes ver el código en github
Resumen
En esta etapa, estoy terminando el artículo de hoy. Creo que entendió que si inmediatamente decidiera mostrar la implementación del inversor DC / AC, entonces el artículo habría sido varias veces más grande o muchos detalles importantes simplemente habrían permanecido detrás de escena, lo que en mi opinión es inaceptable.
Espero que mi artículo ayude a todos a comenzar el desarrollo de esta familia de controladores y comenzar el desarrollo en el campo de la electrónica de potencia y las máquinas herramienta. En el futuro, probablemente escribiré algo más sobre este tema, por ejemplo, me gustaría considerar trabajar con PWM o implementar algún tipo de algoritmo. Lo principal es tener tiempo.
Si tiene alguna pregunta o si algo no funciona para usted, puede escribirme en mensajes privados y trataré de responder sus preguntas y brindarle toda la asistencia posible en el estudio. ¡Te deseo éxito en el entrenamiento!
UPD Gracias por el consejo de
BelerafonL sobre el libro
"Sistemas de control digital integrados de alto rendimiento"