Files
Last update 6 days 23 hours
by
aem357
Files | |
---|---|
PROYECTO_MISE.kicad_pcb | |
PROYECTO_MISE.kicad_pro | |
PROYECTO_MISE.kicad_sch | |
README.md | |
main.c |
main.c#include <msp430.h> #include <stdio.h> #include <stdint.h> #include <string.h> #include <stdlib.h> #include <msp430fr2355.h> uint8_t *PTxData; // Pointer to TX data uint8_t TXByteCtr; uint8_t *PRxData; // Pointer to RX data uint8_t RXByteCtr; uint8_t buffer[3]; uint8_t addr; uint16_t contador; void init_timers(void) { TB0CTL |= TBSSEL__SMCLK; TB0CCR0 = 16000; TB0CCTL0 |= CCIE; } void delay_ms(uint16_t time) // Added proper parameter type { contador = 0; TB0CTL = TBSSEL__SMCLK | MC__UP | TBCLR; // Use ACLK, up mode, clear timer while (contador < time) { // Wait for timer interrupt } TB0CTL = !MC__UP; // Stop timer } void init_LCD () { //¡¡¡¡¡APUNTES PARA HACER LUEGO!!!! //P2.4 -> Activar Reset //Delay 1ms //P2.4 -> Desactivar Reset //Delay 1ms //INICIALIZAR EL LCD //Hacer que el LCD trabaje a 3.3V // Enviamos: //0X3E: Slave sel //0X00: RS = 0. Los siguientes bits son comandos //0x39 //0x14 //0x54 //0x6F //0x0C //0x01 //Detenemos la comunicacion //Entre cada comando un delay de 10ms //Bits a configurar: //RS = 0; Lo que se envian son comandos/instrucciones //RS = 1; Lo que se envian son datos //RW = 0; Escritura //RW = 1; Lectura //Slave Address = 0x3E // //Para mandar datos al LCD: //0X3E: Slave sel //0X40: RS = 1. Los siguientes bits son datos //0Xxx: Dato //Para no tener que escribir todo el rato, usamos la función sprintf //sprintf(mensaje, "Hola mundo"); //I2C_send(0x3E, mensaje, strlen(mensaje)); //Para ahorrar mandar el RS=1, en vez de mandar 0X40 y luego el dato, //Mandamos sprintf(mensaje, "@Hola mundo") ya que el @ es el 0X40 // El mensaje habrá que hacerlo de tamaño 19-20 aproximadamente } void init_GPIOs(void) { P2SEL0 &= ~BIT0 & ~BIT1 & ~BIT2 & ~BIT3 & ~BIT4; P2SEL1 &= ~BIT0 & ~BIT1 & ~BIT2 & ~BIT3 & ~BIT4; // Configurem els Pins P2.0-P2.4 com a GPIO (P2.0-P2.3 Para Joystick, P2.4 para Reset del LCD) P1SEL0 &= ~BIT5; P1SEL1 &= ~BIT5; // Configurem el pin P1.5 com a GPIO (R3 del Joystick) P4SEL0 &= ~BIT0 & ~BIT1 & ~BIT2 & ~BIT3; P4SEL1 &= ~BIT0 & ~BIT1 & ~BIT2 & ~BIT3; // Configurem els pins P4.0-P4.3 com a GPIO (Pines de conector del robot) P1DIR &= ~BIT5; // Asignamos P1.5 como Input P2DIR &= ~BIT0 & ~BIT1 & ~BIT2 & ~BIT3; // Asignamos P2.0-P2.3 como Inputs P2DIR |= BIT4; // Asignamos P2.4 como Input } void init_clocks(void) { // Configure one FRAM waitstate as required by the device datasheet for MCLK operation beyond 8MHz before configuring the clock system FRCTL0 = FRCTLPW | NWAITS_1; P2SEL1 |= BIT6 | BIT7; // P2.6~P2.7: crystal pins do { CSCTL7 &= ~(XT1OFFG | DCOFFG); // Clear XT1 and DCO fault flag SFRIFG1 &= ~OFIFG; // ESTE CODIGO ES SOLO PARA DEBUGGING DEL RELOJ // Dado que en nuestra placa, los pines 2 y 3 (P1.0 y P1.1) están ocupados por los LDR, no podemos usarlos para debuggear el reloj } while (SFRIFG1 & OFIFG); // Test oscillator fault flag __bis_SR_register(SCG0); // disable FLL CSCTL3 |= SELREF__XT1CLK; // Set XT1 as FLL reference source //CSCTL1 = DCOFTRIMEN_1 | DCOFTRIM0 | DCOFTRIM1 | DCORSEL_5; // DCOFTRIM=5, DCO Range = 16MHz** CSCTL1 = DCORSEL_5; // DCOFTRIM=5, DCO Range = 16MHz CSCTL2 = FLLD_0 | 487; // DCOCLKDIV = 16MHz __delay_cycles(3); __bic_SR_register(SCG0); // enable FLL //Software_Trim(); // Software Trim to get the best DCOFTRIM value** CSCTL4 = SELMS__DCOCLKDIV | SELA__XT1CLK; // set XT1 (~32768Hz) as ACLK source, ACLK = 32768Hz // default DCOCLKDIV as MCLK and SMCLK source P1DIR |= BIT0 | BIT1; // set SMCLK, ACLK pin as output P1SEL1 |= BIT0 | BIT1; // set SMCLK and ACLK pin as second function PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode to activate previously configured port settings } void init_i2c() { P1SEL0 |= BIT2 | BIT3; // P4.6 SDA i P4.7 SCL com a USCI si fem server USCI B1 UCB0CTLW0 |= UCSWRST; // Aturem el mòdul //El configurem com a master, sÃncron i mode i2c, per defecte, està en single-master mode UCB0CTLW0 |= UCMST | UCMODE_3 | UCSSEL_2; // Use SMCLK, UCB0BR0 = 160; // fSCL = SMCLK(16MHz)/160 = ~100kHz UCB0BR1 = 0; UCB0CTLW0 &= ~UCSWRST; // Clear SW reset, resume operation UCB0IE |= UCTXIE0 | UCRXIE0; // Habilita les interrupcions a TX i RX } //Envia una sèrie de "n_dades" a la adreça "addr" del I2C void I2C_send(uint8_t addr, uint8_t *buffer, uint8_t n_dades) { UCB0I2CSA = addr; //Coloquem l’adreça de slave PTxData = buffer; //adreça del bloc de dades a transmetre TXByteCtr = n_dades; //carreguem el número de dades a transmetre; UCB0CTLW0 |= UCTR | UCTXSTT; //I2C en mode TX, enviem la condició de start __bis_SR_register(LPM0_bits | GIE); //Entrem a mode LPM0, enable interrupts __no_operation(); //Resta en mode LPM0 fins que es trasmetin les dades while (UCB0CTLW0 & UCTXSTP); //Ens assegurem que s'ha enviat la condició de stop } void I2C_receive(uint8_t addr, uint8_t *buffer, uint8_t n_dades) { PRxData = buffer; //adreça del buffer on ficarem les dades rebudes RXByteCtr = n_dades; //carreguem el número de dades a rebre UCB0I2CSA = addr; //Coloquem l’adreça de slave UCB0CTLW0 &= ~UCTR; //I2C en mode Recepció while (UCB0CTLW0 & UCTXSTP); //Ens assegurem que el bus està en stop UCB0CTLW0 |= UCTXSTT; //I2C start condition en recepció __bis_SR_register(LPM0_bits | GIE); //Entrem en mode LPM0, enable interrupts __no_operation(); // Resta en mode LPM0 fins que es rebin totes les dades } main(void) { WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer init_clocks(); init_GPIOs(); init_i2c(); init_LCD(); init_timers(); __enable_interrupt(); while(1) { buffer[0] = 0X0B; buffer[1] = 0X01; buffer[2] = 0X04; addr = 0x10; I2C_send(addr,buffer,3); delay_ms(100); buffer[0] = 0X0B; buffer[1] = 0X00; buffer[2] = 0X00; addr = 0x10; I2C_send(addr,buffer,3); delay_ms(100); buffer[0] = 0X0B; buffer[1] = 0X04; buffer[2] = 0X01; addr = 0x10; I2C_send(addr,buffer,3); delay_ms(100); } }; #pragma vector = USCI_B0_VECTOR __interrupt void ISR_USCI_I2C(void) { switch(__even_in_range(UCB0IV,12)) { case USCI_NONE: break; // Vector 0: No interrupts case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG case USCI_I2C_UCNACKIFG: break; // Vector 4: NACKIFG case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG case USCI_I2C_UCRXIFG0: // Vector 10: RXIFG if (RXByteCtr) { *PRxData++ = UCB0RXBUF; // Mou la dada rebuda a l’adreça PRxData if (RXByteCtr == 1) // Queda només una? UCB0CTLW0 |= UCTXSTP; // Genera I2C stop condition } else { *PRxData = UCB0RXBUF; // Mou la dada rebuda a l’adreça PRxData __bic_SR_register_on_exit(LPM0_bits); // Exit del mode baix consum LPM0, activa la CPU } RXByteCtr--; // Decrement RX byte counter break; case USCI_I2C_UCTXIFG0: // Vector 12: TXIFG if (TXByteCtr>0) // Check TX byte counter { UCB0TXBUF = *PTxData++; // Carrega el TX buffer amb la dada a enviar TXByteCtr--; // Decrementa TX byte counter } else { UCB0CTLW0 |= UCTXSTP; // I2C stop condition UCB0IFG &= ~UCTXIFG; // Clear USCI_B1 TX int flag __bic_SR_register_on_exit(LPM0_bits); // Exit del mode baix consum LPM0, activa la CPU } default: break; } } #pragma vector=TIMER0_B0_VECTOR // Timer B0 __interrupt void Timer_B (void) { contador++; TB0CCTL0 &= ~CCIFG; // Clear interrupt flag }