Advertisement
DrAungWinHtut

piclcd.c

Jul 16th, 2023
1,000
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.86 KB | None | 0 0
  1.  
  2. // PIC16F18877 Configuration Bit Settings
  3.  
  4. // 'C' source line config statements
  5.  
  6. // CONFIG1
  7. #pragma config FEXTOSC = OFF    // External Oscillator mode selection bits (Oscillator not enabled)
  8. #pragma config RSTOSC = HFINT1  // Power-up default value for COSC bits (HFINTOSC (1MHz))
  9. #pragma config CLKOUTEN = OFF   // Clock Out Enable bit (CLKOUT function is disabled; i/o or oscillator function on OSC2)
  10. #pragma config CSWEN = ON       // Clock Switch Enable bit (Writing to NOSC and NDIV is allowed)
  11. #pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable bit (FSCM timer enabled)
  12.  
  13. // CONFIG2
  14. #pragma config MCLRE = ON       // Master Clear Enable bit (MCLR pin is Master Clear function)
  15. #pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
  16. #pragma config LPBOREN = OFF    // Low-Power BOR enable bit (ULPBOR disabled)
  17. #pragma config BOREN = ON       // Brown-out reset enable bits (Brown-out Reset Enabled, SBOREN bit is ignored)
  18. #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices)
  19. #pragma config ZCD = OFF        // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.)
  20. #pragma config PPS1WAY = ON     // Peripheral Pin Select one-way control (The PPSLOCK bit can be cleared and set only once in software)
  21. #pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will cause a reset)
  22.  
  23. // CONFIG3
  24. #pragma config WDTCPS = WDTCPS_31// WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)
  25. #pragma config WDTE = OFF       // WDT operating mode (WDT Disabled, SWDTEN is ignored)
  26. #pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)
  27. #pragma config WDTCCS = SC      // WDT input clock selector (Software Control)
  28.  
  29. // CONFIG4
  30. #pragma config WRT = OFF        // UserNVM self-write protection bits (Write protection off)
  31. #pragma config SCANE = available// Scanner Enable bit (Scanner module is available for use)
  32. #pragma config LVP = ON         // Low Voltage Programming Enable bit (Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.)
  33.  
  34. // CONFIG5
  35. #pragma config CP = OFF         // UserNVM Program memory code protection bit (Program Memory code protection disabled)
  36. #pragma config CPD = OFF        // DataNVM code protection bit (Data EEPROM code protection disabled)
  37.  
  38. // #pragma config statements should precede project file includes.
  39. // Use project enums instead of #define for ON and OFF.
  40.  
  41.  
  42. #include <xc.h>
  43. #include <stdint.h>
  44. #include <stdio.h>
  45.  
  46. // LCD module connections
  47. #define LCD_RS PORTCbits.RC0
  48. #define LCD_EN PORTEbits.RE0
  49. #define LCD_D4 PORTCbits.RC4
  50. #define LCD_D5 PORTCbits.RC5
  51. #define LCD_D6 PORTCbits.RC6
  52. #define LCD_D7 PORTCbits.RC7
  53. #define LCD_DATA_PORT PORTC
  54.  
  55. // Seven-segment display connections (example)
  56. #define SEGMENT_A PORTBbits.RB0
  57. #define SEGMENT_B PORTBbits.RB1
  58. #define SEGMENT_C PORTBbits.RB2
  59. #define SEGMENT_D PORTBbits.RB3
  60. #define SEGMENT_E PORTBbits.RB4
  61. #define SEGMENT_F PORTBbits.RB5
  62. #define SEGMENT_G PORTBbits.RB6
  63. #define _XTAL_FREQ 10000
  64.  
  65. // Function prototypes
  66. void LCD_Init();
  67. void LCD_Cmd(unsigned char);
  68. void LCD_Char(unsigned char);
  69. void LCD_String(const char*);
  70. void LCD_Clear();
  71. void Display_Oxygen_Level(uint16_t);
  72. void Display_Time(uint16_t);
  73. void Display_Temperature(uint16_t);
  74. uint16_t ADC_Read(uint8_t channel);
  75.  
  76. // Global variables
  77. volatile uint16_t oxygenLevel = 0;
  78. volatile uint16_t timerCount = 0;
  79. volatile uint16_t temperature = 0;
  80.  
  81.  
  82. void main(void) {
  83.     // Initialize LCD and other modules
  84.     LCD_Init();
  85.  
  86.     // Initialize ADC for oxygen level and temperature readings
  87.     //ADCON1bits.ADFM = 1;    // Right justify result
  88.     //ADCON1bits.ADCS = 0b111;    // FOSC/64 as the conversion clock source
  89.     //ADCON1bits.ADPREF = 0b00;   // VREF+ = AVDD, VREF- = AVSS
  90.     ADCON0bits.ADON = 1;    // Enable ADC module
  91.  
  92.     // Initialize Timer1 for time conversion
  93.     //T1CONbits.TMR1CS = 0;   // Timer1 clock source is FOSC/4
  94.     //T1CONbits.T1CKPS = 0b11;    // Timer1 prescaler 1:8
  95.     TMR1 = 0;   // Clear Timer1 register
  96.     T1CONbits.TMR1ON = 1;   // Start Timer1
  97.  
  98.     while (1) {
  99.         // Read oxygen level from potentiometer
  100.         oxygenLevel = ADC_Read(14);
  101.  
  102.         // Read temperature from temperature sensor
  103.         temperature = ADC_Read(2);
  104.  
  105.         // Display oxygen level on LCD
  106.         LCD_Clear();
  107.         LCD_String(" Oxygen Level:");
  108.         LCD_Cmd(0xC0);  // Move cursor to the second line
  109.         Display_Oxygen_Level(oxygenLevel);
  110.  
  111.         // Convert 13 seconds to 24 hours and display on seven-segment display
  112.         Display_Time(13);
  113.  
  114.         // Display temperature on LCD (optional)
  115.         //LCD_Clear();
  116.         //LCD_String("Temperature:");
  117.         //LCD_Cmd(0xC0);  // Move cursor to the second line
  118.         //Display_Temperature(temperature);
  119.  
  120.         __delay_ms(500);    // Delay between consecutive readings
  121.     }
  122.  
  123.     return;
  124. }
  125.  
  126. void LCD_Init() {
  127.     // Configure LCD pins as output
  128.     TRISEbits.TRISE0 = 0;
  129.     TRISCbits.TRISC0 = 0;
  130.     TRISCbits.TRISC1 = 0;
  131.     TRISCbits.TRISC4 = 0;
  132.     TRISCbits.TRISC5 = 0;
  133.     TRISCbits.TRISC6 = 0;
  134.     TRISCbits.TRISC7 = 0;
  135.  
  136.     __delay_ms(15);
  137.  
  138.     LCD_Cmd(0x02);  // Return home
  139.     LCD_Cmd(0x28);  // 4-bit mode - 2 line display - 5x7 font
  140.     LCD_Cmd(0x0C);  // Display ON - Cursor OFF - Blink OFF
  141.     LCD_Cmd(0x06);  // Increment cursor - No shift
  142.     LCD_Cmd(0x80);  // Address DDRAM with 0 offset 80h
  143. }
  144.  
  145. void LCD_Cmd(unsigned char command) {
  146.     LCD_RS = 0;     // Command mode
  147.     LCD_DATA_PORT = (LCD_DATA_PORT & 0x0F) | (command & 0xF0);   // Send higher nibble
  148.     LCD_EN = 1;     // Enable pulse
  149.     __delay_us(1);
  150.     LCD_EN = 0;
  151.     __delay_us(200);
  152.     LCD_DATA_PORT = (LCD_DATA_PORT & 0x0F) | ((command << 4) & 0xF0);   // Send lower nibble
  153.     LCD_EN = 1;     // Enable pulse
  154.     __delay_us(1);
  155.     LCD_EN = 0;
  156.     __delay_ms(2);
  157. }
  158.  
  159. void LCD_Char(unsigned char data) {
  160.     LCD_RS = 1;     // Data mode
  161.     LCD_DATA_PORT = (LCD_DATA_PORT & 0x0F) | (data & 0xF0);   // Send higher nibble
  162.     LCD_EN = 1;     // Enable pulse
  163.     __delay_us(1);
  164.     LCD_EN = 0;
  165.     __delay_us(200);
  166.     LCD_DATA_PORT = (LCD_DATA_PORT & 0x0F) | ((data << 4) & 0xF0);   // Send lower nibble
  167.     LCD_EN = 1;     // Enable pulse
  168.     __delay_us(1);
  169.     LCD_EN = 0;
  170.     __delay_ms(2);
  171. }
  172.  
  173. void LCD_String(const char* text) {
  174.     while (*text != '\0') {
  175.         LCD_Char(*text++);
  176.     }
  177. }
  178.  
  179. void LCD_Clear() {
  180.     LCD_Cmd(0x01);  // Clear display
  181.     __delay_ms(2);
  182. }
  183.  
  184. void Display_Oxygen_Level(uint16_t level) {
  185.     char buffer[5];
  186.     sprintf(buffer, "%3u%%", level);
  187.     LCD_String(buffer);
  188. }
  189.  
  190. void Display_Time(uint16_t seconds) {
  191.     uint16_t hours = seconds / 3600;
  192.     uint16_t minutes = (seconds % 3600) / 60;
  193.     seconds = seconds % 60;
  194.  
  195.     // Display hours on seven-segment display (example)
  196.     SEGMENT_A = hours % 10;
  197.     SEGMENT_B = (hours / 10) % 10;
  198.     SEGMENT_C = (hours / 100) % 10;
  199.     SEGMENT_D = (hours / 1000) % 10;
  200.     // ...
  201.  
  202.     // Display minutes on seven-segment display (example)
  203.     SEGMENT_E = minutes % 10;
  204.     SEGMENT_F = (minutes / 10) % 10;
  205.     // ...
  206.  
  207.     // Display seconds on seven-segment display (example)
  208.     SEGMENT_G = seconds % 10;
  209.     // ...
  210. }
  211.  
  212. void Display_Temperature(uint16_t temp) {
  213.     char buffer[6];
  214.     float temperature = (float)temp * 0.48876 - 50.0; // Example conversion formula
  215.     sprintf(buffer, "%.2fC", temperature);
  216.     LCD_String(buffer);
  217. }
  218.  
  219. uint16_t ADC_Read(uint8_t channel) {
  220.     //ADCON0bits.CHS = channel;    // Select ADC channel    
  221.     ADCON0bits.ADGO = 1;    // Start ADC conversion
  222.  // Wait for ADC conversion to complete
  223.     while (ADCON0bits.ADGO)
  224.         ;
  225.  
  226.     // Return the ADC result
  227.     return ((ADRESH << 8) + ADRESL);
  228. }
  229.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement