Capacidades do módulo EPWM
- As saídas EpwmA epwmB podem funcionar como:
- operação de borda única
- operação simétrica dual-edge
- operação assimétrica de borda dupla
- O tempo morto pode ser configurado
- O evento TZ pode ser configurado e o estado lógico de ambas as saídas HI e LO pode ser definido.
- Um evento de interrupção ou evento SOC para o ADC pode ser configurado.
Vamos nos aproximar dos blocos principais: em que consiste o módulo ePWM e a que ele está conectado.

Como você pode ver na figura, não há muitos blocos no módulo ePWM. Portanto, faz sentido considerar o que cada módulo é responsável e começar com sinais.
- Os sinais EPWMxA e EPWMxB são provavelmente os sinais de saída mais óbvios. O estado lógico normal é HI ou LO, dependendo de como a ação de saída está configurada
- TZ1 — TZ6 — . , , , . , EPWMxA EPWMxB . , , - , , . . , .
- EPWMxSYNCI EPWMxSYNCO — , , .
- Sinais EPWMxSOCA e EPWMxSOCB - aqui tudo é mais do que claro a partir do nome. Esses eventos podem definir eventos SOC para o ADC.
- Sinais EPWMxTZINT e EPWMxINT - aqui um evento de interrupção no TZ e em eventos relacionados ao próprio PWM, por exemplo, gerando uma interrupção no período PWM.
Agora vamos passar para os
módulos Time base (TB) - o módulo é responsável pelo tempo do evento de cada módulo ePWM. Não entraremos em todas as configurações deste módulo, acho que é suficiente prestar atenção ao fato de que existem 3 modos de funcionamento do contador:
- Modo de contagem para cima e para baixo
- Modo de contagem crescente
- Modo de contagem decrescente

E também há uma configuração de sincronização do temporizador configurando o
módulo de bit TBCLKSYNC Counter compare (CC) - através dele, apenas configuramos nosso ciclo de trabalho.
Módulo Action-Qualifier (AQ) - através dele você pode configurar o estado de um evento. E para saídas, você pode configurar as seguintes ações:
- Definido para o estado HI
- Definido para o estado LO
- Executar inversão de estado
- Nada para fazer
Módulo Dead-Band Submodule (DB) - este módulo pode ser usado para definir bandas mortas para canais PWM. Não será segredo para ninguém que as chaves do transistor não mudam instantaneamente e, para evitar uma situação em que a chave de meia-ponte superior não tem tempo para fechar e a inferior já está aberta, eles definem um atraso para mudar para o estado HI e antes mudar para o estado LO.
Módulo Trip-Zone Submodule (TZ) - conforme mencionado acima, este módulo está associado ao tratamento de condições de emergência. Aqui podemos escolher 1 de 4 ações.
- Definido para o estado HI
- Definido para o estado LO
- Definir estado de alta impedância
- Nada para fazer
O evento que aciona a ação do módulo TZ pode ser acionado tanto por software quanto por hardware. Além disso, uma chamada de interrupção é fornecida.
Agora vamos passar das palavras à prática.
Primeiro, você precisa configurar o GPIO para uma função epwm alternativa
EALLOW;
// pull-up
GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0x000;
GpioCtrlRegs.GPAPUD.bit.GPIO1 = 0x000;
// GPIO EPWM1A
GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0x001;
GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0x001;
EDIS;
A seguir, quando já tivermos configurado o GPIO, podemos prosseguir com as diferentes configurações. Para configurar a operação PWM, você precisa decidir o que deseja obter. Vamos começar com a frequência TBCLK. É determinado pela fórmula:
Aqui é preciso atentar para o fato de que CLKDIV é 1 por padrão, com HSPCLKDIV tudo é diferente, por padrão é 2. Isso deve ser levado em consideração, pois há momentos em que as pessoas esquecem. Ao carregar um programa na RAM, geralmente HSPCLKDIV = 1, respectivamente, esse problema não é percebido imediatamente.
Decidimos a frequência do clock de TBCLK. Mas teríamos que escolher como o contador funcionará para nós. Por recessão, por aumentar, e quem sabe desta e daquela forma, para isso é necessário configurar o cadastro adequado, por exemplo:
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
No futuro, para que ninguém se sinta intimidado por macros, determinaremos de onde elas vêm. Essas definições são definidas em um arquivo denominado DSP2833x_EPwm_defines.h.
Em seguida, você precisa decidir como nossos GPIOs reagirão ao atingir certos valores de TBCTR. Existem opções mais do que suficientes. Eles são mostrados na tabela abaixo:

Em seguida, precisamos decidir qual comportamento queremos das portas A e B, ou seja, queremos que elas estejam conectadas entre si ou que possam trabalhar de forma independente. Se quisermos que a porta A seja a mestre, apenas anotamos as ações para ela, por exemplo (caso de contagem crescente):
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;
EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR;
se quisermos independência para a segunda porta, adicione:
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;
EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;
Para mais detalhes sobre as configurações, você precisa consultar a imagem acima para apenas uma adição, há um pouco mais registros AQCTLA do que o mostrado na tabela, isso não altera muito a imagem, mas apenas detalhes são introduzidos em relação a qual caso o contador atingiu o valor desejado, por exemplo, ao contar em início ou contagem regressiva. Mais resumidamente sobre os bits podem ser encontrados no corte do arquivo .h do sistema
struct AQCTL_BITS { // bits description
Uint16 ZRO:2; // 1:0 Action Counter = Zero
Uint16 PRD:2; // 3:2 Action Counter = Period
Uint16 CAU:2; // 5:4 Action Counter = Compare A up
Uint16 CAD:2; // 7:6 Action Counter = Compare A down
Uint16 CBU:2; // 9:8 Action Counter = Compare B up
Uint16 CBD:2; // 11:10 Action Counter = Compare B down
Uint16 rsvd:4; // 15:12 reserved
};
Se tivermos 2 portas ePWM funcionando de forma independente e quisermos definir o tempo morto, precisamos definir o registro para o estado desejado, por exemplo:
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
Agora que decidimos a descrição da periferia, podemos prosseguir com exemplos específicos.
Configurando ePWM no modo de contagem
Aqui está um exemplo sem tempo morto e a porta A e a porta B funcionam de forma independente. Quando A está ativo, B está inativo.
EPwm1Regs.TBPRD = 150000 / 5; // . 150 / 5000
// 50%
EPwm1Regs.CMPA.half.CMPA = EPwm1Regs.TBPRD / 2;
EPwm1Regs.TBPHS.half.TBPHS = 0;
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;
EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE;
EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW;
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_DISABLE;
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0;
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;
EPwm1Regs.AQCTLA.bit.PRD = AQ_CLEAR;
EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;
EPwm1Regs.AQCTLB.bit.PRD = AQ_SET;
EPwm1Regs.AQCTLB.bit.CAU = AQ_CLEAR;
No oscilograma você pode ver o resultado obtido:

Agora você pode tentar adicionar o tempo morto, para isso adicionamos:
EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
EPwm1Regs.DBCTL.all = BP_ENABLE + POLSEL_ACTIVE_HI_CMP; // db
EPwm1Regs.DBFED = 300; // = 150 * 2 = 300
EPwm1Regs.DBRED = 300;
O tempo morto é contado da mesma forma que a frequência, de acordo com a fórmula:
E agora temos tempo morto do jeito que queríamos.

E se precisarmos desamarrar as portas A e B? Isso também acontece. Tudo é simples aqui. Retornamos ao primeiro exemplo e apagamos as últimas 4 linhas e escrevemos cada ciclo de trabalho nos seguintes registradores.
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET;
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR;
EPwm1Regs.AQCTLB.bit.ZRO = AQ_SET;
EPwm1Regs.AQCTLB.bit.CBU = AQ_CLEAR;
EPwm1Regs.CMPA.half.CMPA = EPwm1Regs.TBPRD / 2; // 50%
EPwm1Regs.CMPB = EPwm1Regs.TBPRD / 3; // 33%
Agora temos essa imagem. Você pode definir o ciclo de serviço para cada canal separadamente.

Para o modo de decaimento, tudo é aproximadamente o mesmo. Há uma diferença com a contagem regressiva no modo up-down. Aqui, a frequência do shim é calculada usando a fórmula:
O mesmo é verdade para o tempo morto.
Provavelmente, a única coisa importante que não foi considerada é a configuração do TZ, bem, agora vamos nos alongar neste módulo com mais detalhes.
Para acionar programaticamente um evento de alarme, basta configurar os seguintes registros:
EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
EPwm1Regs.TZCTL.bit.TZB = TZ_FORCE_LO;
O alarme PWM pode ser chamado e redefinido usando os seguintes comandos:
//
EALLOW;
EPwm1Regs.TZFRC.bit.OST = 0x001;
EDIS;
//
EALLOW;
EPwm1Regs.TZCLR.bit.OST = 0x0001;
EDIS;
Se quisermos chamar o sinal TZ em hardware, tudo fica ainda mais fácil, através do registrador TZSEL configuramos o TZ que precisamos, mas além disso, precisamos configurar o GPIO para TZ.
Conclusão
Se alguém achar este artigo interessante, posso escrever mais alguns artigos de uma maneira mais ou menos acelerada. Pretendo considerar o módulo can, gostaria de dma, e talvez também escreva um pequeno artigo sobre IQMath da ti com suas bibliotecas.