Após a introdução de como funciona o PWM do MSP430, utilizarei o Code Composer Studio da Texas para compilar um exemplo prático de seu uso. Farei uso das definições dos registradores que já vem junto com as bibliotecas disponibilizadas pelo fabricante então, por simplificação, não irei me preocupar em detalhes sobre como deixar claro máscaras de bits utilizadas, endereços dos registrados ou outros aspectos relacionados a um nível mais baixo de codificação do dispositivo. Para esse exemplo, estudar o "msp430G2553.h" para ver as definições constantes no arquivo.
1. CONFIGURAÇÃO DO WATCHDOG
A primeira coisa a se configurar deve ser o watchdog do sistema que, conforme nota abaixo, é automaticamente configurado após um PUC do controlador.
Observação do watchdog no "slau144i" |
Os registradores relacionados ao watchdog são os listados na tabela abaixo e vamos dar uma olhada no WDCTL para ver o que encontramos.
Como não irei utilizar o watchdog nesse exemplo, irei desligá-lo setando o bit WDTHOLD (isso ajuda também a economizar gasto de energia). Para que seja aceita uma gravação nesse registro, é necessário que seja escrito nos seus 8 bits mais significativos o valor 5Ah, conforme orienta tabela abaixo. Esse valor é chamado de senha para alterações no watchdog (WDTPW) e qualquer tentativa de escrita nesse registrador que viole essa condição faz com que haja um reset no sistema.
Dessa forma, para desligar o watchdog, faremos:
WDTCTL = WDTPW + WDTHOLD;
Como explicado no início, para maiores detalhes, estudar as definições do microcontrolador utilizado na biblioteca específica.
2. CONFIGURAÇÃO ENTRADAS/SAÍDAS
O MSP430G2553 possui dois timers, conforme pode ser visto na arquitetura publicada na primeira parte deste artigo. Irei utilizar o TIMER1_A3 neste exemplo, utilizando dois blocos de captura/comparação para gerar dois sinais PWM com mesma frequência mas de largura diferentes.
Do datasheet do dispositivos, encontramos a seguinte tabela relacionando os sinais do Timer. Vamos escolher como pinos dos PWMs a serem gerados o P2.2 e P2.4 e vamos utilizar os blocos de captura/comparação CCR1 e CCR2 respectivamente para acionar esses pinos de I/O através das saídas TA1 e TA2.
Tabela Timer1_A3 do datasheet [1] |
Para isso, olhando o manual da família [2], vemos que é necessário configurarmos os registradores PxSEL e PxSEL2 para que os pinos tenham a função escolhida (vários pinos tem suas funções multiplexadas com os diversos hardwares de dispositivo).
Tabela dos registros de seleção de função dos pinos do manual [2] |
O modo de seleção dos pinos P2.2 e P2.4 para que funcionem com as saídas TA1 e TA2 pode ser encontrado no datasheet [1] do dispositivo na tabela abaixo. Nela podemos ver que os bits 2 e 4 do P2DIR devem ser setados (para os pinos serem saídas), os mesmos bits do registrador P2SEL também devem ser setados e do registrador P2SEL2 deve ser ressetado.
Iremos fazer isso usando:
P2DIR |= (BIT2+BIT4); // P2.2 e P2.4 como output
P2SEL |= (BIT2+BIT4); // P2.2 para TA1.1 e P2.4 para TA1.2
P2SEL2 = 0;
3. CONFIGURAÇÃO DE CLOCK
As possíveis fontes de clock para o controlador está descrita no manual da família [1], conforme abaixo:
Descrição das possíveis fontes de clock, segundo manual [1] |
O controlador que vem na placa da launchpad da versão que eu possuo não vem com cristal soldado. Na verdade ele vem até com um cristal de 32768Hz a parte que pode ser soldado, mas eu não fiz isso. Por conta disso, irei utilizar o DCO (Digitally Controlled Oscillator) como fonte de clock.
Algo importante de saber é sobre o clock após o PUC é conforme abaixo. Para maiores detalhes, recomendo a leitura desse capítulo no manual [1].
Ainda no manual [2], encontramos uma tabela com os valores pré-calibrados para uso do VCO:
Nesse exemplo, utilizarei o DCO configurado com um clock de 1MHz. Codificando, eu fiz desse modo:
if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
FaultRoutine();
BCSCTL1 = CALBC1_1MHZ; // Configuração da faixa DCO
DCOCTL = CALDCO_1MHZ; // Configuração dos DCO step e Modulo
BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO
IFG1 &= ~OFIFG; // Reseta OSCFault flag
BCSCTL2 |= SELM_0 + DIVM_0 + DIVS_0; //SELM_0 = seleciona Master Clock como sendo DCO; MCLK = DCO, SMCLK = DCO
if (CALBC1_1MHZ ==0xFF || CALDCO_1MHZ == 0xFF)
FaultRoutine();
BCSCTL1 = CALBC1_1MHZ; // Configuração da faixa DCO
DCOCTL = CALDCO_1MHZ; // Configuração dos DCO step e Modulo
BCSCTL3 |= LFXT1S_2; // LFXT1 = VLO
IFG1 &= ~OFIFG; // Reseta OSCFault flag
BCSCTL2 |= SELM_0 + DIVM_0 + DIVS_0; //SELM_0 = seleciona Master Clock como sendo DCO; MCLK = DCO, SMCLK = DCO
Explicando o código acima, inicialmente é realizado um teste para ver se o conteúdo dos registradores que possuem os valores pré-calibrados são válidos ou não. Caso não sejam válidos (valores 0xFF), então o controlador vai para uma rotina de falha e fica lá presa.
Caso os valores sejam diferentes e sejam válidos, então os valores são copiados para os registros DCOCTL e BCSCTL1. Embora não seja usado nesse exemplo, configuramos o VLO como fonte de clock para os modos de low power do controlador.
Na sequencia, o flag indicador de falta do oscilador é resetado (esse bit tem que ser restado por software quando ocorre uma falha). Nesse caso, ele é resetado por estarmos inicializando o sistema.
Por fim, escolhemos o DCO como fonte dos clocks internos ao chip.
Continua no próximo post...
Na sequencia, o flag indicador de falta do oscilador é resetado (esse bit tem que ser restado por software quando ocorre uma falha). Nesse caso, ele é resetado por estarmos inicializando o sistema.
Por fim, escolhemos o DCO como fonte dos clocks internos ao chip.
Continua no próximo post...
[1] Datasheet MSP430G255: http://www.ti.com/lit/ds/symlink/msp430g2553.pdf
[2] Manual da família: http://www.ti.com/lit/ug/slau144j/slau144j.pdf
Nenhum comentário:
Postar um comentário