Desenvolvimento de software para controle de motor DSP TMS320F28

No meu primeiro artigo, falei sobre essa família de controladores; mais de uma dúzia de pessoas me escreveram na MP com perguntas sobre o assunto, embora esse não fosse o tópico do artigo. As pessoas categoricamente não quiseram ir ao Google, falando sobre a falta de informação. Fiquei um pouco surpreso e decidi verificar - na verdade, em russo, praticamente não há nada na família C2000 (no contexto do AVR, STM) e, o mais importante, não há guias de início claros. As informações podem ser encontradas em inglês, mas, novamente, não são suficientes. Para mim, isso é um tanto surpreendente, já que essa família não tem alguns anos. Portanto, foi decidido o melhor de sua capacidade de influenciar a situação.

Quem precisa desses controladores em princípio ... Deseja montar um inversor de solda? Fonte de alimentação ininterrupta? Alisador de banho de galvanoplastia? Frequência? Um inversor para energia alternativa? Máquina CNC? Se pelo menos um ponto é sobre você, o artigo é dedicado a você!

Outros leitores também estarão interessados ​​em aprender sobre o controlador "novo e velho", por que ele é necessário e como trabalhar com ele. Essa família é muito simples (muito mais simples que STM, LPC e outro Cortex), as pedras são fáceis de comprar (também existem Ali), permitem implementar soluções industriais altamente confiáveis, pois você pode construir praticamente qualquer sistema de controle industrial.

Você já decidiu que esse controlador é o seu sonho e está pronto para correr para a batalha? Em seguida, compramos por US $ 17 a seguinte depuração do F28027-LaunchPad:


Você comprou? Agora você pode entrar em batalha. Se surgiu a questão de onde comprar "melhor" e "mais barato", então vamos à loja oficial. Vamos aqui e vemos o preço de US $ 17. Por esse valor, você receberá uma taxa de depuração original e a entrega do correio na porta. Encomendei uma vez na China para entrega, resultou em US $ 16 e está com desconto e cupom, além de uma viagem "bônus" aos correios. Portanto, eu recomendo que é o oficial. Vamos lá!

Visão geral da série C2000


Você pode ler o máximo de detalhes sobre tudo no site oficial , é claro, em inglês. Vou falar brevemente sobre isso e expressar meus pensamentos sobre o aplicativo. Por favor, note que esta é apenas minha especulação e eles não reivindicam a verdade.

Primeiro, algumas palavras sobre o C2000 em geral. Características distintivas da família, associadas ao seu principal objetivo de controle motor, são a presença de HRPWM (PWM de alta precisão) e CLA (coprocessador). O último está realmente ausente no Piccolo TMS320F2802x mais novo, mas não é necessário por lá, o principal é o HRPWM em vigor. O que é ... O próprio HRPWM é um PWM regular, é muito preciso e o tempo de gravação e configuração para um novo ciclo de trabalho é significativamente mais rápido. Isso possibilita obter, por exemplo, um seno perfeitamente modelado em um inversor DC / CA ou controlar motores de passo em uma máquina CNC com precisão muito alta.

O CLA é essencialmente um núcleo completo, mas não tem acesso a periféricos, apenas ao núcleo principal e à memória. Serve para descarregar o núcleo principal da computação. Esse coprocessador digere de maneira fácil e natural os dados flutuantes, o que é importante ao implementar vários algoritmos, filtros e muito mais.



Vou falar sobre duas famílias principais que você provavelmente encontrará:

  • Piccolo. Os controladores mais jovens, mas também os mais baratos. Meu TMS320F28027 é desta família. Se você decidir desenvolver eletrônicos de potência para fins comerciais, essas serão suas principais pedras - elas são bastante baratas, pagáveis ​​(LQFP, QFN, TSSOP) e permitem implementar quase tudo. Por exemplo, seu desempenho é suficiente para um PFC bifásico, um inversor para painéis solares, um conversor de frequência de até 10 kW com controle vetorial, etc. Como você pode ver, este é um segmento de produtos que é comprado por pessoas comuns e empresas, o que significa que é muito procurado. As principais limitações são a frequência de 60 MHz, um número limitado de canais PWM.
  • Delfino. Ideologicamente, estes são todos iguais Piccolo, apenas inflados com meldonium. O que é isso expresso - a frequência é de 200 MHz, nas pedras antigas já existem 2 núcleos completos + 2 coprocessadores, gabinetes grandes e, portanto, muitas pernas, muitos canais PWM, muitos ADCs e, em geral, muito. Ou seja, em pedras mais antigas, temos 4 núcleos com uma frequência de 200 MHz, um desempenho de 800 MIPS, o que é bastante impressionante. Esse poder pode ser usado de diferentes maneiras, mas a aplicação principal são sistemas algoritmicamente complexos, por exemplo, o retificador de Vienne ou qualquer outra coisa. Também em um desses controladores, você pode implementar todo o sistema de controle de uma máquina CNC, por exemplo, fresagem ou corte a chama de metal.

Finalização da placa de depuração


Quando você recebe uma caixa com uma placa de depuração, encontrará o quartzo e os capacitores ausentes. Eles não são necessários, mas é aconselhável usar drogas. Eu não tenho mais quartzo no HC-49, então tive que pedir emprestado a um amigo. Ele escolhe AVR e STM, então encontrou apenas 8 MHz. Soldado. Adicionei 22 capacitores pF da memória antiga, como fiz em mega na escola.

Esta solução não é a melhor e está conectada à configuração do PLL. O multiplicador máximo para PLL é x12 (mais pode ser, mas não é recomendado, e funciona de maneira torta). A frequência máxima é de 60 MHz. O valor máximo do divisor na saída PLL é 3. A frequência do quartzo é 8 MHz. Não posso multiplicar por 8 por um número inteiro e obter 60. Estamos procurando o valor total mais próximo, neste caso 240. Ou seja, multiplique 8 por 30 e, em seguida, dividindo por 4, obtenho os cobiçados 60 MHz, mas o problema é que o multiplicador x30 PLL é inaceitável , divider / 4 também está indisponível. Existem 2 saídas:

  • Ruim: multiplique a frequência de 8 MHz por 7 e divida por 1 e obtenha 56 MHz. Você pode multiplicar por 8 e obter 64 MHz, funcionará de forma estável, mas em ambos os casos a frequência não é máxima de 60 MHz. Não é suficiente perfeccionismo, infelizmente. Eu tenho apenas essa opção, soldado 8 MHz e fez uma frequência de 56 MHz.
  • Bom: compre o quartzo a 10 ou 20 MHz (melhor que 10) e multiplique por 6, bem, divida por 1, obtemos os estimados 60 MHz. Eu moro fora da cidade e, honestamente, era muito preguiçoso ir a uma loja local, na qual não é fato que haja quartzo de 10 MHz. Obviamente, o circuito RC interno e o quartzo de 8 MHz serão usados ​​para treinamento, mas em seus projetos futuros, coloque o quartzo de 10 MHz, não os gigantescos mutantes no pacote HC-49.

Arquitetura e recursos periféricos


Tudo o que acontecerá a seguir se aplica ao controlador TMS320F28027. Para começar, vejamos a estrutura retirada da folha de dados :



A primeira coisa que você deve prestar atenção é que a RAM é dividida em 3 setores: M0, M1 e SARAM. Os volumes desses setores de memória no nosso caso são 1k, 1k e 4k. Vale ressaltar que, neste caso, a palavra não é de 8 bits, mas de 16 bits, ou seja, de uma forma mais familiar, é de 2 kB + 2 kB + 8 kB. A peculiaridade deste módulo é que os setores M0 e M1 são mais rápidos que os 8 kB restantes de RAM. Formalmente, você pode levar isso como um cache. Os setores M0 e M1 geralmente armazenam os dados usados ​​com mais freqüência, bem como os dados mais críticos para o desempenho da memória. Por padrão, podemos usar o vinculador para especificar o que e onde está armazenado, mas não abordarei este tópico neste artigo, aqui é necessário pelo menos um artigo separado.

A segunda característica importante é que todos os periféricos têm clock do barramento do sistema, ou seja, a partir de 60 MHz (no meu caso, 56 MHz). Como exemplo, darei os microcontroladores STM32, onde a frequência do núcleo é, por exemplo, 180 MHz para F4, mas os periféricos são sincronizados através de uma série de divisores. Eu chamo essa abordagem de "megahertz falso" para mim, embora isso seja muito exagerado. Portanto, 60 MHz para TMS320F28 e 180 MHz para stm32 não são tão diferentes e, se você se lembrar da presença de CLA, 60 + 60 MHz são pelo menos comparáveis. É claro que essa comparação não está correta, mas deixa claro que não apenas os megahertz estão cansados.

Também é um ponto interessante - preste atenção à estrutura geral: HRPWM, ADCs, comparadores com um DAC interno, módulo de processamento de codificador (eCAP) ... Um conversor de frequência pronto com controle vetorial em sua forma pura! Essa é toda a essência dessa família - minimalismo. Por um lado, a periferia é bastante ruim em comparação com o Cortex, mas, por outro lado, é suficiente implementar um conversor de frequência, dc / dc, dc / ac e um driver de motor de passo. Devido a isso, trabalhar com os controladores TMS320F28 é muito simples, compreensível e não sobrecarregado com ações desnecessárias. Mas se de repente você precisar de 3 UARTs, e para eles um par de i2c e mais 3 SPIs, esses controladores definitivamente não são para você - eles têm tarefas diferentes.

Ambiente de Desenvolvimento



Você já viu o logotipo inicial? Lembre-se dela. Se você decidir começar a usar artigos no desenvolvimento dos heróis do artigo, esse software será todo seu e, como você vê, o software será chamado controlSUITE .

Esta aplicação é uma coleção e biblioteca de tudo o que você precisa para desenvolver software para a família de controladores C2000. Instalar este aplicativo é a primeira coisa a fazer e ver sua composição; ele contém:

  • Descrição de todos os controladores e placas de depuração existentes com base neles. Fontes de circuitos, placas de circuito impresso, listas técnicas, principalmente no Altium Designer
  • Exemplos de circuitos e design de placas de circuito impresso
  • Bibliotecas principais para desenvolvimento de firmware
  • Bibliotecas de matemática e DSP, inclusive para uso com CLA
  • Um exemplo de projetos de software para cada tipo de periférico
  • Um grande número de apnouts para a implementação da maioria dos algoritmos para controle de motores, conversores dc / dc, controladores MPPT e outros sistemas
  • Um conjunto de programas que permitem criar um sistema de gerenciamento de mecanismo sem programação, simplesmente usando um ambiente gráfico
  • O próprio IDE, que será desenvolvido

Tudo o que descrevi acima é muito breve e modesto. Você levará algumas semanas para ver e rolar pelo menos na diagonal. Obviamente, você não precisará da maior parte dessa quantidade de dados no início, mas precisará se lembrar para onde ir se algo for incompreensível para você e estranho.

Agora, com o que trabalharemos hoje é o IDE, cuja parte gráfica se baseia na conhecida Eclipse. O compilador não é o GCC, mas o próprio Texas, que na minha opinião subjetiva é definitivamente melhor que o primeiro. Embora haja suspeitas de que isso seja completamente dopado do mesmo modo gcc. O ambiente de desenvolvimento é chamado Code Composer Studio , a versão atual 7.4.

Criação de projeto


No começo, eu queria implementar uma tarefa idêntica ao primeiro artigo, ou seja, desenhar um seno. Em princípio, na estrutura de um artigo, isso poderia ter sido feito deixando para trás um quadro de um volume muito grande de pequenas coisas, mas como você sabe, a essência está precisamente nas pequenas coisas. Existem vários artigos sobre o TMS na Internet, mas todos são muito superficiais e se resumem ao tipo de "copiar isso e tudo funciona", ou seja, o processo e a ideologia em si não são considerados. Portanto, na estrutura deste artigo, criaremos um projeto, limparemos os componentes desnecessários, configuramos o firmware na memória flash do controlador e aprenderemos a trabalhar com o GPIO, e eles são muito interessantes aqui.

Faça o download do CCS7 no site do fabricante, instale e comece a criar o projeto da maneira usual: Arquivo → Novo → Projeto CCS ...


Vemos essa janela e nela precisamos selecionar o controlador que nos interessa, no meu caso é TMS320F28027, indicar o nome do projeto e prescrever o caminho em que ele será armazenado. Primeiro, você precisa criar uma pasta onde o projeto será armazenado. O nome do projeto e o nome da pasta podem não corresponder. Clique no botão Concluir e nosso projeto é criado.

Agora você precisa preencher o nosso projeto com conteúdo e conectá-lo. Antes disso, para melhorar a estrutura do projeto, crie este conjunto de pastas:


  • inc - uma pasta que contém todos os arquivos de cabeçalho
  • system_inc - esta seção armazenará os arquivos de cabeçalho das bibliotecas padrão, os arquivos que nós mesmos criaremos, por exemplo, main.c, estão na pasta inc. Isso não quebrará algo sem pensar ou removerá desnecessariamente
  • src - pasta com todas as fontes
  • system_src - pasta com arquivos de origem para bibliotecas padrão

Observe que essa estrutura não é algum tipo de dogma, mas é apenas minha ideia de pedido. Embora eu o recomende a pessoas com experiência mínima, com o tempo você mudará para se adequar à sua visão de mundo, mas, por enquanto, isso minimizará o número de batentes.

Agora crie o arquivo main.h na pasta inc e conecte-o ao main.c. Através dele, conectará as bibliotecas de base. E antes de começar a transferir bibliotecas e outros arquivos, vamos escrever o caminho para as pastas onde nossos futuros arquivos de cabeçalho serão armazenados nas configurações do projeto. Para fazer isso, clique com o botão direito do mouse no projeto (Teste) na árvore do projeto e clique em Propriedades na parte inferior ou pressione Alt + Enter . Na janela que se abre, vá para Compilar → Compilador C2000 → Incluir opções e aqui precisamos de dois caminhos existentes - registre o caminho para as pastas inc e system_inc. Clique em Adicionar , Espaço de trabalho e, em seguida, na pasta inc desejada, faça o mesmo e se apegue à segunda pasta. Assim, prescrevemos caminhos relativos; ao transferir um projeto, você não precisará reconfigurar nada. Como resultado, obtemos uma imagem e clicamos em Ok :



Agora temos um projeto vazio com os caminhos prescritos e outras configurações, resta apenas preenchê-lo com bibliotecas. A única coisa a fazer é verificar se tudo está conectado. Em teoria, você deve obter um código e uma imagem e compilar o projeto. Para fazer isso, pressione CTRL + B ou vá para Projeto → Compilar tudo na parte superior. O projeto deve compilar sem erros e ter a seguinte aparência (a imagem é clicável):



Agora vamos falar um pouco sobre o vinculador. Inicialmente, ao criar um projeto, o IDE gera o arquivo 28027_RAM_lnk.cmd , coloca nosso programa na RAM durante a depuração e o firmware. Isso é conveniente quando estamos depurando, porque Os recursos de memória flash não são desperdiçados e a entrada de depuração na RAM é significativamente mais rápida. Mas e se quisermos costurar em flash? Para fazer isso, existe outro arquivo de link que colocará nosso programa em flash. Vou mostrar esta opção.

Antes de tudo, exclua o arquivo 28027_RAM_lnk.cmd . Como eu disse - controlSUITE é o nosso tudo. Nós abrimos. Agora vá em inglês → Dispositivo → Piccolo F2802x → Bibliotecas de suporte → Arquivos de cabeçalho para F28027x . À direita, vemos pastas - estas são as bibliotecas padrão e tudo o que é necessário, incluindo vinculadores. Agora vamos para a pasta f2802x_common → cmd e aqui vemos um conjunto de vinculadores para todas as pedras na linha. Não é difícil adivinhar os arquivos _RAM para fazer upload de código na RAM e sem essa tag para fazer o upload via flash. Pegamos o arquivo F28027.cmd e o copiamos para o nosso projeto, em vez do antigo vinculador remoto.

Agora é hora de migrar as próprias bibliotecas. Vamos para a pasta f2802x_common → source e vemos vários arquivos. Existem dois tipos de bibliotecas: registradores padrão (semelhantes ao CMSIS) e algum tipo de SPL. Nesse caso, estamos interessados ​​apenas na primeira visualização, ou seja, arquivos com o prefixo f2802x_ . Claro, você pode arrastar todos eles para o nosso projeto, mas por que entupi-lo se não usarmos tudo? Se você precisar de algo, no futuro, basta adicioná-lo. Por enquanto, nos restringimos aos seguintes conjuntos de arquivos:

  • f2802x_codestartbranch.asm
  • f2802x_defaultisr.c
  • f2802x_piectrl.c
  • f2802x_pievect.c
  • f2802x_sysctrl.c

Copiamos o arquivo de dados e colamos em nossa pasta system_src . Agora vamos para a pasta f2802x_headers → source e pegamos o arquivo F2802x_GlobalVariableDefs.c de lá e copiamos novamente para a pasta system_src . Em seguida, vá para a pasta f2802x_headers → cmd e copie o arquivo F2802x_Headers_nonBIOS.cmd de lá para a mesma pasta. Isso completa o preenchimento da pasta system_src e prossegue para os cabeçalhos.

Nós vamos para a pasta f2802x_headers → incluímos e copiamos todos os arquivos de lá para a pasta system_inc . Agora vamos para a pasta f2802x_common → source e copiamos os arquivos de lá:

  • f2802x_examples.h
  • f2802x_globalprototypes.h
  • f2802x_i2c_defines.h
  • f2802x_epwm_defines
  • f2802x_swprioritizedisrlevels.h
  • f2802x_defaultisr.h

Devemos obter esta imagem na árvore do projeto:


Agora você precisa conectar as bibliotecas básicas, o arquivo main.h assume o seguinte formato:

#pragma once #include "F2802x_Device.h" #include "F2802x_examples.h" 

Estamos tentando compilar. Se o projeto foi compilado sem erros e avisos, tudo está conectado corretamente. Se isso não aconteceu, verifique duas vezes todas as 10 vezes e, se não der certo, escreva para o PM - eu ajudarei, como Owl disse: "Baz-woz-mEz-bottom, ou seja, por nada . "

Inicialização do controlador e sistema de relógio


Nesta seção, escreveremos uma função que inicializa o timer do watchdog e os vetores de interrupção e define os sinalizadores de interrupção para zero. Também configuramos o sistema de relógio, como resultado do quartzo externo e não da cadeia RC interna se tornar a fonte do relógio, configurar o PLL e ativar o relógio para todos os periféricos.

Para a precisão do código, proponho colocar todas as inicializações básicas em um arquivo separado, cuja interface será a função void InitStartSystem (void) . Para fazer isso, crie os arquivos systemInitStart.he systemInitStart.c . Escreverei imediatamente uma função e simplesmente analisamos seu conteúdo:

 void InitStartSystem (void) { DisableDog(); XtalOscSel(); InitPll(TMS320_PLLCR, TMS320_DIVSEL); InitPeripheralClocks(); InitPieCtrl(); InitPieVectTable(); } 

Todas as funções chamadas em InitStartSystem () são padrão. Aconselho que você veja em detalhes como eles são implementados; para isso, você pode pressionar CTRL e clicar na função de seu interesse. Você já olhou? Agora repasse brevemente ...

  • DisableDog () - a função desativa o "cão". Esta é uma etapa obrigatória ao configurar a parte principal de periféricos críticos, por exemplo, um sistema de relógio. No código da biblioteca, você costuma ver isso, ele será duplicado e duplicado
  • XtalOscSel () - esta função implementa a mudança de uma fonte de relógio interna para um quartzo externo. Um ponto importante! Há um erro na biblioteca padrão com esta função - ela não é declarada. Vamos para o arquivo f2802x_globalprototypes.he entre todos os outros, adicionamos a linha extern void XtalOscSel (void)



    O segundo ponto importante! Vá para a função XtalOscSel e exclua a função de atraso.



    O terceiro ponto importante! Vamos ao arquivo f28027x_exmaples.h e comentamos a função de implementação de atraso.


  • InitPll (TMS320_PLLMUL, TMS320_DIVSEL) - a função configura o PLL. Dois valores são transferidos para ele: multiplicador e divisor. Seu valor é especificado no arquivo de cabeçalho. Um ponto importante! Abrimos essa função na biblioteca e você precisa comentar o atraso na parte inferior

  • InitPll (TMS320_PLLMUL, TMS320_DIVSEL) - a função configura o PLL. Dois valores são transferidos para ele: multiplicador e divisor. Seu valor é especificado no arquivo de cabeçalho. Um ponto importante! Abrimos essa função na biblioteca e você precisa comentar o atraso na parte inferior
  • InitPeripheralClocks () - essa função simplesmente habilita o relógio para toda a periferia. Sim para todos. O C2000 não é uma solução para glândulas alimentadas por bateria,
    esta solução de unidades-dezenas-centenas de quilowatts e patético 2-3 mA não desempenhará um papel aqui. Bem, você não precisa se lembrar toda vez que liga o relógio para algum tipo de SPI ou não
  • InitPieCtrl () - a função desativa todas as interrupções e redefine os sinalizadores de interrupção
  • InitPieVectTable () - a função preenche a tabela com vetores de interrupção

Na verdade, aqui está tudo inicialização. Eu acho que muitos notaram os "pontos importantes" associados à função Delay . Por que cortamos na videira? Sim, tudo é simples - é uma muleta.

Os engenheiros de TI adicionaram esses atrasos completamente desnecessários a algumas das funções, adicionadas em atualizações recentes. Por que - um mistério não só para mim. Registros e outras entradas críticas já estão protegidos, portanto não tornará nosso controlador estúpido. A propósito, ao inicializar em eletrônica de potência, é impossível "embotar", caso contrário, serão mariquinhas. Portanto, esqueça as funções de atraso e outros males para sempre, apenas temporizadores! Atrasos são permitidos apenas para alguns fins educacionais, por exemplo, piscando rapidamente com um LED.

Para verificar se o código está funcionando, chamamos a função de inicialização em main, compile, flash e hook no osciloscópio GPIO18 . Este pino é semelhante ao MCO do STM32, o que significa que emite a frequência do sistema. Um osciloscópio deve ver um sinal com uma frequência de 56 MHz. Se o osciloscópio for bom, você verá o meandro, se o chinês (até bom), provavelmente será algo mais próximo do seno. A configuração do GPIO18 na frequência do sistema de saída pode ser vista na função InitPeripheralClocks () . Primeiro, você precisa “conectar” o gpio à saída de frequência e depois definir o divisor para 1:

  GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 3; // GPIO18 = XCLKOUT SysCtrlRegs.XCLK.bit.XCLKOUTDIV=2; // Set XCLKOUT = SYSCLKOUT/1 

Configuração GPIO


Para trabalhar com essa família, precisamos apenas de um manual de referência, que os desenvolvedores de TI dividiram em vários arquivos, cada um dos quais descreve uma certa periferia, o que é muito conveniente. Faça o download da folha de dados aqui e vá para a seção Suporte da documentação na página 126. Aqui vemos um conjunto de links para a documentação com sua breve descrição: errata, um guia para iniciar o gerenciamento do mecanismo e guias em cada periferia. Estamos interessados ​​em um documento chamado Guia de Referência de Controle e Interrupções do Sistema TMS320F2802x / TMS320F2802xx , que contém a descrição do GPIO e outras configurações básicas do sistema que nos interessam. Observamos o diagrama de blocos do GPIO:



Vemos uma imagem bastante familiar das portas de entrada / saída do dispositivo. Aqui e a capacidade de ativar o suspender interno e o uso de um sinal com o GPIO para interrupções e outras comodidades. A principal característica desse periférico no C2000 é a possibilidade de suprimir interferências de hardware, por exemplo, o barulho de contatos mecânicos de um botão. Vejamos um diagrama interessante:



Ele mostra o princípio de ler o status das entradas. Na maioria dos controladores, o estado de entrada é lido com a frequência de clock dessa periferia, ou seja, por padrão com uma frequência de 56 MHz no nosso caso, e para o mesmo stm nas famílias mais antigas, essas frequências são ainda mais altas. Acho que todo mundo entende que, com essa frequência, o controlador tem tempo para "ver" qualquer interferência e ruído. Às vezes, essa frequência é necessária e, às vezes, não, por exemplo, se precisarmos pressionar um botão. Por que a entrevistaríamos a cada 18 anos? Portanto, percebemos a possibilidade de reduzir a frequência de clock de uma porta específica usando o registro CTRL e os bits QUALPRDx , onde X assume um valor de 0 a 3: QUALPRD0 é responsável por GPIO0 ... 7, QUALPRD1 é responsável por GPIO8 ... 15 e assim por diante. De fato, este é um divisor de frequência comum com um coeficiente de 1 a 510.



Geralmente não faz sentido interrogar um botão, portanto ajustaremos o divisor para 510, ou seja, ao máximo. Nós olhamos novamente para o diagrama e vemos que o sinal é considerado estável somente quando seu nível não foi alterado por 6 tiques. O número de medidas necessárias para a fixação pode ser 1, 3 ou 6. Quanto maior o divisor e mais ciclos fixamos, mais estável é a proteção contra conversas. Quando há uma conversa de contatos, no início serão transições caóticas de 0 para 1 e vice-versa, quando a conversa passa e o sinal para e não muda por 6 relógios, isso significa que o botão é pressionado. Tudo engenhoso é simples.

Agora, vamos olhar para os principais registros, não tocaremos em interrupções - apenas nas configurações das próprias portas. Primeiro, você precisa dizer que os registros são divididos em 2 tipos: registros de configuração e registros de dados . Os primeiros são responsáveis ​​pela configuração das propriedades, por exemplo, essa entrada ou saída. O segundo grupo é responsável por escrever e ler o status da porta.

Registros de instalação:

  • GPxCTRL - registre-se para escrever o divisor de relógio. Em vez de "x", substituímos a letra "A" - se tivermos GPIO0 ... 31, "B" - se usarmos GPIO32 ... 63 e assim por diante
  • GPAQSELx - registre para definir o número de ticks para fixar o valor na entrada
  • GPAMUX1 é um registro para a seleção de periféricos conectados, por exemplo, indica que GPIO ou UART, ou talvez PWM, estão no pé.
  • GPADIR - Registro de seleção de direção GPIO: entrada ou saída. Por padrão, todas as portas estão configuradas para entrada.
  • GPAPUD é o registro responsável por conectar o suspensor interno ao VCC.
    Vale a pena notar que, para algumas portas, por padrão, o pull-up está desativado e, para uma parte, está ativado.
    Isso é importante lembrar!

Registradores de dados:

  • GPADAT - registro de status de saída. Se a saída estiver configurada para entrada, então lemos o status da entrada. Se estiver configurado para uma saída, podemos escrever o valor que essa saída deve receber, ou seja, 0 ou 1
  • GPASET - registrador configurando a saída para "1". Para definir como "1", você deve escrever "1", ao escrever "0" o comando é ignorado
  • GPACLEAR - registrador configurando a saída para "0". Para definir como "0", você deve escrever "1", ao escrever "0" o comando é ignorado
  • GPATOGGLE é um registro que inverte o valor atual do estado de saída. Para inverter o valor, escreva “1”; ao escrever “0”, o comando é ignorado

Aqui está um conjunto tão simples de registros. Mesmo com a descrição acima, você já pode entender o que precisa ser feito para configurar a porta, mas os engenheiros ou escritores técnicos prudentes da TI fizeram outra instrução passo a passo:



Eu direi imediatamente que as etapas 6 e 7 não são necessárias para nós, porque nem o cão nem a interrupção são usados ​​neste artigo. Descreverei brevemente as etapas restantes para as pessoas que estudaram alemão na escola:

  • Etapa 1 - determine a funcionalidade de saída: que será uma entrada ou saída,
    gpio ou saída para outros periféricos e outras coisas
  • Etapa 2 - ativar ou desativar o pull-up interno
  • Etapa 3 - configurar a proteção de relógio e rejeição para uma porta específica
  • Etapa 4 - selecione a função desejada: gpio ou periféricos
  • Etapa 5 - defina a direção da saída: entrada ou saída

Essa é toda a configuração, como você vê, é elementar e logicamente clara. Quero notar imediatamente que não é necessário, nesta ordem, fazer configurações, por exemplo, você pode definir a direção (entrada ou saída) no primeiro passo. Isso não importa.

Super importante!

Ao trabalhar com registros na família C2000, é necessário levar em consideração o momento em que eles estão protegidos. Tudo descrito abaixo se aplica principalmente aos registros do grupo de configuração. Se você analisou cuidadosamente as funções padrão, provavelmente viu comandos estranhos lá: EALLOW; e EDIS; . Comando EALLOW - remove a proteção e fornece acesso ao trabalho com os registros do sistema. Comando EDIS - ativa a proteção traseira e fornece acesso ao trabalho com registros do sistema. Ou seja, qualquer trabalho com registros do sistema SEMPRE deve ser assim:

 EALLOW; //    ,   ,  EDIS; 

Essa operação não é necessária se trabalharmos com registradores de dados, por exemplo, se definirmos nossa saída como "1" usando o registrador GPxSET , não precisaremos remover a proteção e, consequentemente, ativá-lo novamente. A documentação em toda parte diz o que precisa ser protegido e o que não é, por exemplo, assim:



Com base em tudo isso, vamos configurar o GPIO0 ... 3 com LEDs para saída. Sugiro colocar todas as configurações do GPIO na função InitLEDgpio e escrever:

 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 padrão, nossos GPIOs já estão configurados como GPIOs, como todos os valores do registro são limpos, o que significa que “0” já está gravado no registro GPAMUX1. Para GPIO0 ... 11, o pull-up é desativado por padrão, para que possamos tomar e determinar a direção do trabalho até a saída usando GPADIR. Se você se lembrar, os LEDs são conectados ao controlador por cátodos, o que significa que imediatamente após a inicialização eles acenderão. Vamos definir essas conclusões diretamente na função de inicialização como "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 você pode ver, não uso o registro GPADAT para escrever, mas uso SET, CLEAR, TOGGLE . Observe também que eu fiz essa entrada fora da zona protegida, ou seja, após o comando EDIS . Agora, na mesma função, configure o GPIO12 para trabalhar com o botão e adicione nossa função:

 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; } 

Antes de tudo, desative o aperto interno escrevendo "1" no registro GPAPUD , porque é ativado pelo GPIO12 por padrão. Como escrevi anteriormente, todas as portas após a inicialização são configuradas para entrada, como zeros são escritos no registro GPADIR , não o configuramos aqui.

Resta configurar a proteção contra rejeição, para isso dividimos os divisores 0xFF , que corresponde ao valor / 510. No registro GPAQSEL1 , escrevemos o valor “10” ou 2, que define o valor para uma amostra de 6 medidas. Feito! Para ler o valor de uma entrada específica, você só precisa ler o valor do registro GPADAT :

 if (GpioDataRegs.GPADAT.bit.GPIO12) { //      +3.3 (. 1)  ,     } 

É assim que interrogamos as conclusões necessárias. Agora vamos chamar a função de configuração gpio em nossa função principal e obter sua forma final:

 void InitStartSystem (void) { DisableDog(); XtalOscSel(); InitPll(TMS320_PLLMUL, TMS320_DIVSEL); InitPeripheralClocks(); InitPieCtrl(); InitPieVectTable(); /*********************************/ InitLEDgpio(); } 

Agora chamamos a função InitStartSystem no corpo principal do programa em main e isso completa a configuração. Nós obtemos o seguinte código:

 #include "main.h" int main (void) { InitStartSystem(); while(1) { } } 

É hora de escrever nosso primeiro programa de teste e testar tudo isso. O algoritmo é este: o LED que fica no GPIO3 pisca e, quando você pressiona o botão no GPIO12, simplesmente acendemos o LED GPIO0. Assim, verificaremos o funcionamento das portas para entrada e saída. Escrevemos o seguinte 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); } } 

Nós compilamos, vamos ao depurador, iniciá-lo e ver como um LED pisca constantemente e, quando você pressiona o botão, outro acende. No final da seção, anexarei um projeto com esse código; se algo não der certo, analise-o. Especialmente para quem é exigente em textos ou não entendeu todos os pontos, sugiro que assista a este vídeo sobre como trabalhar com o GPIO, tudo está acontecendo lá, como na seção "GPIO". Eu aviso que o vídeo por uma hora, sombrio, longo, mas o mais detalhado possível e tudo é visível:



Arquivos do artigo


  • Arquivo com o projeto para o CCS7 faça o download aqui
  • Você pode ver o código no github

Sumário


Nesta fase, estou terminando o artigo de hoje. Eu acho que você entendeu que, se eu decidisse imediatamente mostrar a implementação do inversor DC / CA, o artigo teria sido várias vezes maior ou muitos detalhes importantes simplesmente permaneceriam nos bastidores, o que, na minha opinião, é inaceitável.

Espero que meu artigo ajude todos a iniciar o desenvolvimento dessa família de controladores e a desenvolver no campo da eletrônica de potência e das máquinas-ferramentas. No futuro, provavelmente escreverei algo mais sobre esse tópico, por exemplo, gostaria de considerar trabalhar com o PWM ou implementar algum tipo de algoritmo. O principal é ter tempo.

Se você tiver alguma dúvida ou se algo não der certo para você, escreva-me em mensagens privadas. Tentarei responder às suas perguntas e fornecer toda a assistência possível no estudo. Desejo-lhe sucesso nos treinamentos!

UPD Obrigado pela dica da BelerafonL no livro "Sistemas de controle digital embarcados de alto desempenho"

Source: https://habr.com/ru/post/pt410161/


All Articles