Guest User

Untitled

a guest
Apr 9th, 2025
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.20 KB | None | 0 0
  1. /*
  2. SDA - P1.2
  3. SCL - P1.3
  4.  
  5. RS - P2.0
  6. RW - P2.1
  7. E  - P2.2
  8.  
  9. D0 - P3.0
  10. D1 - P3.1
  11. D2 - P3.2
  12. D3 - P5.3 P3.3 is broken
  13. D4 - P3.4
  14. D5 - P3.5
  15. D6 - P3.6
  16. D7 - P3.7
  17. */
  18.  
  19. #include <msp430.h>
  20. #include <stdint.h>
  21. #include <stdio.h>
  22.  
  23. #define LIS3DH_ADDR     0x19       // I2C address for the LIS3DH (use 0x18 if SDO is low)
  24. #define WHO_AM_I_REG    0x0F       // WHO_AM_I register address (should return 0x33)
  25. #define CTRL_REG1       0x20       // Control register 1; writing here enables the sensor
  26. #define CTRL_REG4       0x23
  27. #define LIS3DH_OUT_X_L                0x28
  28. #define LIS3DH_TEMP_CFG_REG           0x1F
  29.  
  30. int pos = 0;
  31. int line = 0;
  32.  
  33. void delay_ms(unsigned int ms)
  34. {
  35.     while(ms--)
  36.         __delay_cycles(1000);  // 1ms delay if MCLK is 1MHz
  37. }
  38.  
  39. void send_command_lcd(unsigned char data){
  40.     send_raw_lcd(data, 0x0);
  41. }
  42.  
  43. void send_data_lcd(unsigned char data){
  44.     send_raw_lcd(data, BIT0);
  45.     pos++;
  46. }
  47.  
  48. void send_sentence_lcd(char str[]){
  49.     unsigned int j = 0;
  50.     while (str[j] != '\0'){
  51.         send_data_lcd(str[j]);
  52.         delay_ms(1);
  53.         if (pos == 16){
  54.             pos = 0;
  55.             if (line == 0){
  56.                 send_command_lcd(0xC0);
  57.                 line = 1;
  58.             }
  59.             else{
  60.                 send_command_lcd(0x01);
  61.                 line = 0;
  62.             }
  63.            
  64.         }
  65.         j++;
  66.     }
  67. }
  68.  
  69. void set_payload_lcd(unsigned char data){
  70.     P3OUT = data;
  71.     data = data & BIT3;
  72.     P5OUT |= data;
  73.     data = P3OUT;
  74. }
  75.  
  76. void send_raw_lcd(unsigned char data, unsigned char mask){
  77.  
  78.     P2OUT = 0;
  79.     P2OUT |= mask;
  80.     P2OUT &= ~BIT1;
  81.  
  82.     delay_ms(1);
  83.  
  84.     set_payload_lcd(data);
  85.  
  86.     delay_ms(1);
  87.  
  88.     P2OUT |= BIT2;
  89.  
  90.     delay_ms(1);
  91.  
  92.     P2OUT &= ~BIT2;
  93.  
  94.     delay_ms(1);
  95.  
  96.     P5OUT &= ~BIT3;
  97.     P3OUT = 0;
  98.     P2OUT = 0;
  99.  
  100.     delay_ms(1);
  101. }
  102.  
  103. void lcd_init(){
  104.     P5DIR |= BIT3;
  105.     P3DIR |= 0x0FF;
  106.     P2DIR |= 0x07;
  107.  
  108.     send_command_lcd(0x38); // 8 bit mode
  109.  
  110.     send_command_lcd(0x01); // clear screen
  111.  
  112.     send_command_lcd(0x0C); // turn screen on
  113.  
  114.     send_command_lcd(0x06); // set entry mode
  115. }
  116.  
  117. void i2c_init(void){
  118.    
  119.     UCB0CTLW0 |= UCSWRST;
  120.  
  121.     UCB0CTLW0 |= UCMST | UCMODE_3 | UCSYNC;
  122.  
  123.     UCB0CTLW0 |= UCSSEL__SMCLK;
  124.  
  125.     UCB0BRW = 10;
  126.  
  127.     UCB0I2CSA = LIS3DH_ADDR;
  128.  
  129.     P1SEL1 &= ~(BIT2 | BIT3);  // Select primary module function
  130.     P1SEL0 |=  (BIT2 | BIT3);  // for P1.2 (SDA) and P1.3 (SCL)
  131.  
  132.     UCB0CTLW0 &= ~UCSWRST;  // Release I2C module for operation
  133.  
  134. }
  135.  
  136. uint8_t read_i2c(uint8_t reg){ // unsigned integer, 8 bits
  137.     uint8_t data;
  138.  
  139.     while (UCB0STATW & UCBBUSY); // wait until not busy
  140.  
  141.     // Set to Transmit mode and send a START condition with the register address
  142.     UCB0CTLW0 |= UCTR | UCTXSTT;           // UCTR=TX mode, send START
  143.     while (!(UCB0IFG & UCTXIFG0));          // Wait for TX buffer to be ready
  144.     UCB0TXBUF = reg;                      // Send register address
  145.     while (!(UCB0IFG & UCTXIFG0));          // Wait for transmission to complete
  146.    
  147.     // Switch to Receiver mode to read the data
  148.     UCB0CTLW0 &= ~UCTR;                   // Clear UCTR (switch to RX mode)
  149.     UCB0CTLW0 |= UCTXSTT;                 // Send repeated START for reading
  150.     while (UCB0CTLW0 & UCTXSTT);          // Wait until the repeated START is sent
  151.    
  152.     // Send STOP condition; the STOP will be sent after the first byte is received
  153.     UCB0CTLW0 |= UCTXSTP;
  154.     while (!(UCB0IFG & UCRXIFG0));         // Wait for a byte to be received
  155.     data = UCB0RXBUF;                     // Read the received byte
  156.     while (UCB0CTLW0 & UCTXSTP);          // Wait until the STOP condition is sent
  157.    
  158.     return data;
  159. }
  160.  
  161. // Read multiple registers in a single transaction (using auto-increment)
  162. // For the LIS3DH, set the MSB of the register address to enable auto-increment
  163. void readx_i2c(uint8_t startReg, uint8_t *buffer, uint8_t count)
  164. {
  165.     uint8_t regAddr = startReg | 0x80; // Set auto-increment bit (bit 7)
  166.  
  167.     while (UCB0STATW & UCBBUSY);       // Wait until the I2C bus is free
  168.    
  169.     // Transmit phase: send register address with auto-increment enabled
  170.     UCB0CTLW0 |= UCTR | UCTXSTT;        // Set TX mode, send START condition
  171.     while (!(UCB0IFG & UCTXIFG0));      // Wait until TX buffer is ready
  172.     UCB0TXBUF = regAddr;              // Transmit register address
  173.     while (!(UCB0IFG & UCTXIFG0));      // Wait until address transmitted
  174.    
  175.     // Switch to RX mode to read the data
  176.     UCB0CTLW0 &= ~UCTR;               // Clear UCTR to switch to receiver mode
  177.     UCB0CTLW0 |= UCTXSTT;             // Send repeated START for reading
  178.     while (UCB0CTLW0 & UCTXSTT);      // Wait until repeated START is sent
  179.    
  180.     // Read the desired number of bytes
  181.     int i;
  182.     for (i = 0; i < count; i++) {
  183.         if (i == (count - 1)) {        // For the last byte, set the STOP condition
  184.             UCB0CTLW0 |= UCTXSTP;
  185.         }
  186.         while (!(UCB0IFG & UCRXIFG0)); // Wait until a byte is received
  187.         buffer[i] = UCB0RXBUF;         // Store received byte into the buffer
  188.     }
  189.     while (UCB0CTLW0 & UCTXSTP);      // Wait until the STOP condition is complete
  190. }
  191.  
  192. void write_i2c(uint8_t reg, uint8_t value)
  193. {
  194.     // Wait until the I²C bus is free
  195.     while (UCB0STATW & UCBBUSY);
  196.  
  197.     // Set eUSCI_B0 to Transmit mode and issue a START condition
  198.     UCB0CTLW0 |= UCTR | UCTXSTT;
  199.     while (!(UCB0IFG & UCTXIFG0));   // Wait for TX buffer ready
  200.  
  201.     // Send the register address (the location you want to write to)
  202.     UCB0TXBUF = reg;
  203.     while (!(UCB0IFG & UCTXIFG0));   // Wait for the register address to be transmitted
  204.  
  205.     // Send the data byte you wish to write to the register
  206.     UCB0TXBUF = value;
  207.     while (!(UCB0IFG & UCTXIFG0));   // Wait for the data byte to be transmitted
  208.  
  209.     // Issue a STOP condition to end the transaction
  210.     UCB0CTLW0 |= UCTXSTP;
  211.     while (UCB0CTLW0 & UCTXSTP);     // Wait for the STOP condition to complete
  212. }
  213.  
  214. void uint8_to_hex(uint8_t value, char *buf) {
  215.     const char hexDigits[] = "0123456789ABCDEF";
  216.     buf[0] = hexDigits[(value >> 4) & 0x0F];
  217.     buf[1] = hexDigits[value & 0x0F];
  218.     buf[2] = '\0';
  219. }
  220.  
  221. int main(void)
  222. {
  223.     WDTCTL = WDTPW | WDTHOLD;   // Stop watchdog timer
  224.     PM5CTL0 &= ~LOCKLPM5;       // Disable high-impedance mode
  225.  
  226.     // Configure LED on P1.0 for debugging
  227.     P1DIR |= BIT0;      
  228.     P1OUT &= ~BIT0;    
  229.    
  230.     i2c_init();
  231.     lcd_init();
  232.  
  233.     delay_ms(100);
  234.  
  235.     send_sentence_lcd("Hello");
  236.  
  237.     uint8_t whoami = read_i2c(WHO_AM_I_REG);
  238.     if (whoami != 0x33) {
  239.         send_sentence_lcd("Err WHO:");
  240.         char buf[3];
  241.         uint8_to_hex(whoami, buf);
  242.         send_sentence_lcd(buf);
  243.         while (1) {
  244.             P1OUT ^= BIT0;
  245.             delay_ms(1000);
  246.         }
  247.     }
  248.  
  249.  
  250.     uint8_t dataToWrite = 192;
  251.     // 1100000
  252.     // ^^-----
  253.     // 7: ADC enabled
  254.     // 6: Temp enabled
  255.  
  256.     write_i2c(LIS3DH_TEMP_CFG_REG, dataToWrite);
  257.  
  258.     dataToWrite = 71;
  259.     // 01000111
  260.     // ^^^^^^^^
  261.     // 7-4: 50hz
  262.     // 3: Normal mode
  263.     // 2: Z on
  264.     // 1: Y on
  265.     // 0: X on
  266.  
  267.     write_i2c(CTRL_REG1, dataToWrite);
  268.  
  269.     delay_ms(300);
  270.  
  271.     // Variables to hold the sensor data.
  272.     uint8_t dataBuffer[6];
  273.     char outStr[10];
  274.     int16_t x_raw, y_raw, z_raw;
  275.  
  276.     while (1)
  277.     {
  278.         // Use a multi-byte read to grab all six output registers starting at 0x28.
  279.         readx_i2c(LIS3DH_OUT_X_L, dataBuffer, 6);
  280.  
  281.         // Combine the low and high bytes.
  282.         x_raw = (((int16_t)dataBuffer[1]) << 8) | dataBuffer[0];
  283.         y_raw = (((int16_t)dataBuffer[3]) << 8) | dataBuffer[2];
  284.         z_raw = (((int16_t)dataBuffer[5]) << 8) | dataBuffer[4];
  285.  
  286.         // For normal mode (10-bit), shift right by 6 bits to get the valid 10-bit value.
  287.         x_raw = x_raw >> 6;
  288.         y_raw = y_raw >> 6;
  289.         z_raw = z_raw >> 6;
  290.  
  291.         // Clear and update the LCD with the new values.
  292.         send_command_lcd(0x01);
  293.         pos = 0;
  294.         line = 0;
  295.         sprintf(outStr, "X:%d", x_raw);
  296.         send_sentence_lcd(outStr);
  297.         sprintf(outStr, " Y:%d", y_raw);
  298.         send_sentence_lcd(outStr);
  299.         sprintf(outStr, " Z:%d", z_raw);
  300.         send_sentence_lcd(outStr);
  301.  
  302.         delay_ms(1000);
  303.     }
  304. }
  305.  
  306.  
Advertisement
Add Comment
Please, Sign In to add comment