Compiling a C program for a pic microcontroller - error message - c

I have a C program that I am trying to put on my pic but I get the error "3.17 can't open include file "main.h": No such file or directory". This is my first time ever attempting to program a pic.
Here is the program I am trying to put on it.
#include <htc.h>
#include <stdio.h>
#include "main.h"
__CONFIG(FOSC_INTOSC & WDTE_OFF & PWRTE_OFF & MCLRE_ON & CP_OFF & CPD_OFF & BOREN_OFF & CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF);
__CONFIG(WRT_OFF & PLLEN_OFF & STVREN_OFF & BORV_HI & LVP_OFF);
#define _XTAL_FREQ 4000000
int main()
{
int t = 0;
char outStr[8];
char ch;
init();
Lcd_PutStr(0, 0, "Option 1");
Lcd_PutStr(1, 0, "Spec Analyzer");
while (1)
{
// do stuff here
}
}
int init()
{
// Hardware
OSCCON = 0x6A; // 4 MHz oscillator
PORTA = 0; // Clear Port A
LATA = 0;
PORTB = 0; // Clear Port B
LATB = 0;
PORTC = 0; // Clear Port C
LATC = 0;
ANSELA = 0; // Set Port A to digital
ANSELB = 0; // Set Port B to digital
ANSELC = 0; // Set Port C to digital
TRISB = 0; // Set port B to output
TRISC = 0; // Set port C to output
// LCD display
Lcd_Init();
return 0;
}
void ENPulse()
{
LATC |= 0x20;
__delay_us(1);
LATC &= 0xdf;
}
void Lcd_Init()
{
LATC = 0;
__delay_ms(40);
LATC = 0x03;
ENPulse();
__delay_us(37);
Lcd_Cmd(0x28);
__delay_us(37);
Lcd_Cmd(0x28);
__delay_us(37);
Lcd_Cmd(0x0C);
__delay_ms(2);
Lcd_Cmd(0x01);
__delay_us(37);
}
void Lcd_Cmd(byte cmd)
{
LATC = cmd >> 4;
ENPulse();
LATC = cmd & 0x0F; // clear RS (LATC,4)
ENPulse();
__delay_us(100);
}
void Lcd_Data(byte data)
{
LATC = (data >> 4) | 0x10; // set RS (LATC,4)
ENPulse();
LATC = (data & 0x0F) | 0x10; // set RS (LATC,4)
ENPulse();
__delay_us(100);
}
void Lcd_PutStr(int row, int col, char* str)
{
int pos;
// use row and column=-1 for no positioning, i.e. position where last ended
if (row >= 0 && col >= 0)
{
if (row > 0)
row = 0x40; // row 1
else
row = 0; // row 0
pos = row | col | 0x80; // 0x80 is cmd for positioning cursor
Lcd_Cmd(pos);
}
while (*str)
{
Lcd_Data(*str);
str++;
}
}
I am using MPLab and Hi-Tech C with a Pickit3. I based this code off of a sample given to me. I do not know what the purpose of the main.h file is. Any help is appreciated.

After reviewing your errors, you may be able to run the code without main.h. It looks like main.h mostly prototypes the functions at the bottom of the file. Try putting this code between the main and the #define:
int init();
void ENPulse();
void Lcd_Init();
void Lcd_Cmd(byte cmd);
void Lcd_Data(byte data);
void Lcd_PutStr(int row, int col, char* str);
This should at lest reduce most of your errors. It may fix it completely. The idea is that when the compiler first encounters theses functions it doesn't know what they are and it throws errors before it can find them. If there are still errors let me know and I'll try and help more.

Try this code:
#include <htc.h>
#include <stdio.h>
//#include "main.h"
__CONFIG(FOSC_INTOSC & WDTE_OFF & PWRTE_OFF & MCLRE_ON & CP_OFF & CPD_OFF & BOREN_OFF & CLKOUTEN_OFF & IESO_OFF & FCMEN_OFF);
__CONFIG(WRT_OFF & PLLEN_OFF & STVREN_OFF & BORV_HI & LVP_OFF);
#define _XTAL_FREQ 4000000
int init()
{
// Hardware
OSCCON = 0x6A; // 4 MHz oscillator
PORTA = 0; // Clear Port A
LATA = 0;
PORTB = 0; // Clear Port B
LATB = 0;
PORTC = 0; // Clear Port C
LATC = 0;
ANSELA = 0; // Set Port A to digital
ANSELB = 0; // Set Port B to digital
ANSELC = 0; // Set Port C to digital
TRISB = 0; // Set port B to output
TRISC = 0; // Set port C to output
// LCD display
Lcd_Init();
return 0;
}
void ENPulse()
{
LATC |= 0x20;
__delay_us(1);
LATC &= 0xdf;
}
void Lcd_Init()
{
LATC = 0;
__delay_ms(40);
LATC = 0x03;
ENPulse();
__delay_us(37);
Lcd_Cmd(0x28);
__delay_us(37);
Lcd_Cmd(0x28);
__delay_us(37);
Lcd_Cmd(0x0C);
__delay_ms(2);
Lcd_Cmd(0x01);
__delay_us(37);
}
void Lcd_Cmd(byte cmd)
{
LATC = cmd >> 4;
ENPulse();
LATC = cmd & 0x0F; // clear RS (LATC,4)
ENPulse();
__delay_us(100);
}
void Lcd_Data(byte data)
{
LATC = (data >> 4) | 0x10; // set RS (LATC,4)
ENPulse();
LATC = (data & 0x0F) | 0x10; // set RS (LATC,4)
ENPulse();
__delay_us(100);
}
void Lcd_PutStr(int row, int col, char* str)
{
int pos;
// use row and column=-1 for no positioning, i.e. position where last ended
if (row >= 0 && col >= 0)
{
if (row > 0)
row = 0x40; // row 1
else
row = 0; // row 0
pos = row | col | 0x80; // 0x80 is cmd for positioning cursor
Lcd_Cmd(pos);
}
while (*str)
{
Lcd_Data(*str);
str++;
}
}
int main()
{
int t = 0;
char outStr[8];
char ch;
init();
Lcd_PutStr(0, 0, "Option 1");
Lcd_PutStr(1, 0, "Spec Analyzer");
while (1)
{
// do stuff here
}
}

Related

MSP430 UART receiving a string - TX problem

Using MSP430F6736A embedded programming. Code written in Code Composer Studio. I have a problem in my code, but i have no idea what i can do to fix it.
When I compile the program in code composer, works well but UART are sending to PC just ".ø€.ø€.€€x" that means i'm getting only strange charracters
#include "msp430g2553.h"
#include <stdio.h>
float RLDR=0, lux=0, v0=0;
unsigned int ADC10_vetor[16]={0};
unsigned int sum=0;
unsigned char i=0;
unsigned char TX_data[32], tx_index = 0, lux_int =0;
void ini_ucon(void);
void ini_p1_p2(void);
void ini_Timer0(void);
void ini_ADC10(void);
void ini_USCI_UART(void);
void ini_ucon(void){
WDTCTL = WDTPW | WDTHOLD;
DCOCTL = CALDCO_8MHZ;
BCSCTL1 = CALBC1_8MHZ;
BCSCTL2 = DIVS0 + DIVS1; //SMCLK = 1MHz
__enable_interrupt();
}
void ini_p1_p2(void){
P1DIR = 0xFF;
P1OUT = 0x00;
P2DIR = 0xFF;
P2OUT = 0x00;
}
void ini_Timer0(void){
TA0CTL = TASSEL1 + ID1 + ID0 + MC0; //SMCLK = 1MHz/8 = 125000
TA0CCTL1 = OUTMOD0 + OUTMOD1 + OUTMOD2 + OUT;
TA0CCR0 = 62499; //2Hz = 0.5 secs. , TA0CCR0 = 0.5*125000 - 1 = 62499
TA0CCR1 = 31249; //PWM = 50%
}
void ini_ADC10(void){
ADC10CTL0 = ADC10SHT1 + MSC + ADC10ON + ADC10IE;
ADC10CTL1 = INCH0 + INCH2 + SHS0 + ADC10SSEL1 + CONSEQ1;
ADC10AE0 = BIT5; //P1.5 para A5
ADC10DTC0 = 0;
ADC10DTC1 = 16;
ADC10SA = &ADC10_vetor[0];
ADC10CTL0 |= ENC;
}
int main(void){
ini_ucon();
ini_p1_p2();
ini_Timer0();
ini_ADC10();
ini_USCI_UART();
while(1){
}
}
#pragma vector=ADC10_VECTOR
__interrupt void ADC10_RTI(void){
ADC10CTL0 &= ~ENC;
soma = 0;
for(i=0;i<16;i++){
sum = sum + ADC10_vetor[i];
}
sum = sum >> 4;
//RLDR = (42625000)/(3*sum)-10000;
//lux = 500/(RLDR/1000);
//v0=5*(sum/(sum+10000));
v0=sum*(3.6/1024);
RLDR = (10000*(5-v0))/v0;
lux = (500/(RLDR/1000));
lux_int = (unsigned char) lux;
sprintf(&TX_data[0], "LUX = %d \n", lux_int);
UCA0TXBUF = TX_data[0];
tx_index++;
ADC10SA = &ADC10_vetor[0];
ADC10CTL0 |= ENC;
}
#pragma vector=USCIAB0TX_VECTOR
__interrupt void RTI_USCI_UART(void)
{
IFG2 &= ~UCA0TXIFG;
if(TX_data[tx_index] == '\0'){
tx_index = 0;
}else{
if(tx_index >= 32){
tx_index = 0;
}else{
UCA0TXBUF = TX_data[tx_index];
tx_index++;
}
}
}
void ini_USCI_UART(void){
UCA0CTL1 |= UCSWRST;
UCA0CTL0 = 0;
UCA0CTL1 = UCSSEL0 + UCSSEL1 + UCSWRST;
UCA0BR0 = 0xA0;
UCA0BR1 = 0x01;
UCA0MCTL = UCBRS1 + UCBRS2;
UCA0STAT = 0;
P1SEL |= BIT2;
P1SEL2 |= BIT2;
UCA0CTL1 &= ~UCSWRST;
IFG2 &= ~UCA0TXIFG;
IE2 |= UCA0TXIE;
}
Does anyone have an idea how to fix this?

why LCD does not display anything

#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <string.h>
#include <stdint.h>
#include "config.h"
#include "Uart.h"
#define _XTAL_FREQ 20000000
#define RS RC0
#define EN RC1
#define D4 RC2
#define D5 RC3
#define D6 RC4
#define D7 RC5
/*
*
*/
void Lcd_Port(char a)
{
if(a & 1)
D4 = 1;
else
D4 = 0;
if(a & 2)
D5 = 1;
else
D5 = 0;
if(a & 4)
D6 = 1;
else
D6 = 0;
if(a & 8)
D7 = 1;
else
D7 = 0;
}
void Lcd_Cmd(char a)
{
RS = 0; // => RS = 0
Lcd_Port(a);
EN = 1; // => E = 1
__delay_ms(4);
EN = 0; // => E = 0
}
int Lcd_Clear()
{
Lcd_Cmd(0);
Lcd_Cmd(1);
}
void Lcd_Set_Cursor(char a, char b)
{
char temp,z,y;
if(a == 1)
{
temp = 0x80 + b - 1;
z = temp>>4;
y = temp & 0x0F;
Lcd_Cmd(z);
Lcd_Cmd(y);
}
else if(a == 2)
{
temp = 0xC0 + b - 1;
z = temp>>4;
y = temp & 0x0F;
Lcd_Cmd(z);
Lcd_Cmd(y);
}
}
void Lcd_Init()
{
Lcd_Port(0x00); // clear latches before enabling TRIS bits
__delay_ms(20);
Lcd_Cmd(0x03);
__delay_ms(5);
Lcd_Cmd(0x03);
__delay_ms(11);
Lcd_Cmd(0x03);
/////////////////////////////////////////////////////
Lcd_Cmd(0x02); //02H is used for Return home -> Clears the RAM and initializes the LCD
Lcd_Cmd(0x02);
Lcd_Cmd(0x08);//Select Row 1
Lcd_Cmd(0x00);//Clear Row 1 Display
Lcd_Cmd(0x0C);//Select Row 2
Lcd_Cmd(0x00);//Clear Row 2 Display
Lcd_Cmd(0x06);
}
void Lcd_Write_Char(char a)
{
char temp,y;
temp = a&0x0F;
y = a&0xF0;
RS = 1; // => RS = 1
Lcd_Port(y>>4); //Data transfer
EN = 1;
__delay_us(40);
EN = 0;
Lcd_Port(temp);
EN = 1;
__delay_us(40);
EN = 0;
}
void Lcd_Write_String(char *a)
{
int i;
for(i=0;a[i]!='\0';i++)
Lcd_Write_Char(a[i]);
}
void Lcd_Shift_Right()
{
Lcd_Cmd(0x01);
Lcd_Cmd(0x0C);
}
void Lcd_Shift_Left()
{
Lcd_Cmd(0x01);
Lcd_Cmd(0x08);
}
int main(int argc, char** argv) {
OSCCONbits.IRCF = 0b1111; //set operating frequency to 31kHz (0b1111) for 16MHz
UART_init();
Lcd_Init();
// ->Setare Pini
//Pini motor DC
ANSELAbits.ANSA0 = 0; //set to digital pin
ANSELAbits.ANSA1 = 0; //set to digital pin
TRISAbits.TRISA0 = 0; //set as output
TRISAbits.TRISA1 = 0; //set as output
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 0;
//Butoane
ANSELAbits.ANSA2 = 0; //set to digital pin
ANSELAbits.ANSA4 = 0; //set to digital pin
ANSELBbits.ANSB4 = 0; //set to digital pin
TRISAbits.TRISA2 = 1; //set as input
TRISAbits.TRISA4 = 1; //set as input
TRISBbits.TRISB4 = 1; //set as input
//LEDuri
//RC6 - RIGHT
//RC6 LEFT
TRISCbits.TRISC6 = 0;
TRISCbits.TRISC7 = 0;
//Set as digital
ANSELCbits.ANSC6 = 0;
ANSELCbits.ANSC7 = 0;
//Folosire LCD
TRISCbits.TRISC0 = 0; //set as output
TRISCbits.TRISC1 = 0; //set as output
TRISCbits.TRISC2 = 0; //set as output
TRISCbits.TRISC3 = 0; //set as output
TRISCbits.TRISC4 = 0; //set as output
TRISCbits.TRISC5 = 0; //set as output
//pull up
//pull upurile
OPTION_REGbits.nWPUEN = 0;
WPUAbits.WPUA2 = 1;
WPUAbits.WPUA4 = 1;
WPUAbits.WPUA0 = 1;
WPUAbits.WPUA1 = 0;
WPUAbits.WPUA3 = 0;
WPUAbits.WPUA5 = 0;
WPUBbits.WPUB4 = 1;
char introducere;
UART_write_string("1. Move to right ");
UART_write('\r');
UART_write_string("2. Move to left");
UART_write('\r');
UART_write_string("4. Stop UART");
UART_write('\r');
PORTCbits.RC6 = 0;
PORTCbits.RC7 = 0;
while(1){
introducere = UART_read();
if (introducere == '1'){
PORTAbits.RA0 = 1;
PORTAbits.RA1 = 0;
PORTCbits.RC6 = 1;
PORTCbits.RC7 = 0;
Lcd_Clear();
Lcd_Set_Cursor(1,1); //Go to the first line
Lcd_Write_String("helo"); //Display String
}
if (introducere == '2' ){
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 1;
PORTCbits.RC6 = 0;
PORTCbits.RC7 = 1;
}
if(PORTAbits.RA2 == 0){ //Right
PORTAbits.RA0 = 1;
PORTAbits.RA1 = 0;
PORTCbits.RC6 = 1;
PORTCbits.RC7 = 0;
}
if(PORTAbits.RA4 == 0){ //left
PORTAbits.RA0 = 0;
PORTAbits.RA1 = 1;
}
if(introducere =='4'){
CREN = 0; //disable receiver
UART_write('\r');
UART_write_string("disable UART!");
UART_write('\r');
}
if(PORTBbits.RB4 == 0){
CREN = 1; //enable receiver
UART_write('\r');
UART_write_string("enable UART!");
UART_write('\r');
}
}
return (EXIT_SUCCESS);
}
The purpose of the project is to create a Dc motor which when we press 1 to rotate to the right and display on the LCD "rotated right", and if we press 2 to rotate to the left and display on the LCD "rotate left".
Used: pic16f1828
LCD: LM016L
I connected: RS (LCD) -> RC0 (pic), EN -> RC1, D4 -> RC2, D5 -> RC3, D6 -> RC4, D7 -> RC5
The program works well, the only problem I have is the fact that when I press "1" I want HELO to appear on LCD (it doesn't matter the arrangement). Till now it does not appear on LCD, is not just about HELLo, nothing is displayed, I can only see that it starts, I don't understand where the problem is.
Your implementation for writing to the HD44780 using a 4-bit parallel interface is wrong.
This is a complete, builds with MPLABX v5.50 and XC8 v2.32, demo that does display "Hello" on line 1 of the LCD module:
/*
* File: main.c
* Author: dan1138
* Target: PIC16F1828
* Compiler: XC8 v2.32
* IDE: MPLABX v5.50
*
* Created on January 23, 2022, 11:27 AM
*
* PIC16F1828
* +-----------:_:-----------+
* VDD -> : 1 VDD VSS 20 : <- VSS
* RA5 <> : 2 OSC2 PGD 19 : <> RA0 ICD_PGD
* RA4 <> : 3 OSC1 PGC 18 : <> RA1 ICD_PGC/D5
* ICD_VPP RA3 -> : 4 VPP/MCLRn 17 : <> RA2
* LCD_D7 RC5 <> : 5 16 : <> RC0 LCD_RS
* LCD_D6 RC4 <> : 6 15 : <> RC1 LCD_EN
* LCD_D5 RC3 <> : 7 14 : <> RC2 LCD_D4
* RC6 <> : 8 13 : <> RB4
* RC7 <> : 9 12 : <> RB5
* RB7 <> : 10 11 : <> RB6
* +-------------------------+
* DIP-20
*
* Description:
*
* See: https://stackoverflow.com/questions/70800375/why-lcd-does-not-display-anything
*/
// CONFIG1
#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is MCLR)
#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)
#pragma config BOREN = OFF // Brown-out Reset Enable (Brown-out Reset disabled)
#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
// CONFIG2
#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)
#pragma config PLLEN = OFF // PLL Enable (4x PLL disabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled)
/*
* Tell compiler what we intend to set the system oscillator frequency as.
*/
#define _XTAL_FREQ (16000000UL)
#include <xc.h>
#include <stdio.h>
/* Define the LCD interface and character size */
#define LCD_FORMAT (FOUR_BIT & LINES_5X7)
/* Define the LCD port pins */
#define LCD_DATA_BITS_MASK 0x3C
#define LCD_PORT_OUT LATC
#define LCD_PORT_DIR TRISC
#define LCD_RS_PIN LATCbits.LATC0
#define LCD_EN_PIN LATCbits.LATC1
#define LCD_D4_PIN LATCbits.LATC2
#define LCD_D5_PIN LATCbits.LATC3
#define LCD_D6_PIN LATCbits.LATC4
#define LCD_D7_PIN LATCbits.LATC5
#define LCD_RS_PIN_DIR TRISCbits.TRISC0
#define LCD_EN_PIN_DIR TRISCbits.TRISC1
#define LCD_D4_DIR TRISCbits.TRISC2
#define LCD_D5_DIR TRISCbits.TRISC3
#define LCD_D6_DIR TRISCbits.TRISC4
#define LCD_D7_DIR TRISCbits.TRISC5
/* Clear display command */
#define CLEAR_DISPLAY 0b00000001
/* Return home command */
#define RETURN_HOME 0b00000010
/* Display ON/OFF Control defines */
#define DON 0b00001111 /* Display on */
#define DOFF 0b00001011 /* Display off */
#define CURSOR_ON 0b00001111 /* Cursor on */
#define CURSOR_OFF 0b00001101 /* Cursor off */
#define BLINK_ON 0b00001111 /* Cursor Blink */
#define BLINK_OFF 0b00001110 /* Cursor No Blink */
/* Cursor or Display Shift defines */
#define SHIFT_CUR_LEFT 0b00010011 /* Cursor shifts to the left */
#define SHIFT_CUR_RIGHT 0b00010111 /* Cursor shifts to the right */
#define SHIFT_DISP_LEFT 0b00011011 /* Display shifts to the left */
#define SHIFT_DISP_RIGHT 0b00011111 /* Display shifts to the right */
/* Function Set defines */
#define FOUR_BIT 0b00101111 /* 4-bit Interface */
#define EIGHT_BIT 0b00111111 /* 8-bit Interface */
#define LINE_5X7 0b00110011 /* 5x7 characters, single line */
#define LINE_5X10 0b00110111 /* 5x10 characters */
#define LINES_5X7 0b00111011 /* 5x7 characters, multiple line */
/* Start address of each line */
#define LINE_ONE 0x00
#define LINE_TWO 0x40
static void LCD_E_Pulse(void)
{
LCD_EN_PIN = 1;
__delay_us(4);
LCD_EN_PIN = 0;
__delay_us(4);
}
static void LCD_DelayPOR(void)
{
__delay_ms(15);
}
static void LCD_Delay(void)
{
__delay_ms(5);
}
static void LCD_PutByte(unsigned char LCD_Data)
{
LCD_PORT_DIR &= ~LCD_DATA_BITS_MASK; /* make LCD data bits outputs */
/* send first(high) nibble */
LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;
if(LCD_Data & 0x10) LCD_D4_PIN = 1;
if(LCD_Data & 0x20) LCD_D5_PIN = 1;
if(LCD_Data & 0x40) LCD_D6_PIN = 1;
if(LCD_Data & 0x80) LCD_D7_PIN = 1;
LCD_E_Pulse();
/* send second(low) nibble */
LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK;
if(LCD_Data & 0x01) LCD_D4_PIN = 1;
if(LCD_Data & 0x02) LCD_D5_PIN = 1;
if(LCD_Data & 0x04) LCD_D6_PIN = 1;
if(LCD_Data & 0x08) LCD_D7_PIN = 1;
LCD_E_Pulse();
LCD_PORT_DIR |= LCD_DATA_BITS_MASK; /* make LCD data bits inputs */
}
void LCD_SetPosition(unsigned char data)
{
LCD_RS_PIN = 0;
LCD_PutByte((unsigned char)(data | 0x80));
__delay_us(40);
}
void LCD_WriteCmd(unsigned char data)
{
LCD_RS_PIN = 0;
LCD_PutByte(data);
__delay_ms(4);
}
void LCD_WriteData(unsigned char data)
{
LCD_RS_PIN = 1;
LCD_PutByte(data);
LCD_RS_PIN = 0;
__delay_us(40);
}
void LCD_Init(void)
{
unsigned char LCD_Data;
LCD_PORT_DIR &= ~LCD_DATA_BITS_MASK; /* make LCD data bits outputs */
LCD_EN_PIN_DIR = 0; /* make LCD Enable strobe an output */
LCD_RS_PIN_DIR = 0; /* make LCD Register select an output */
LCD_EN_PIN = 0; /* set LCD Enable strobe to not active */
LCD_RS_PIN = 0; /* set LCD Register select to command group */
LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK; /* set LCD data bits to zero */
LCD_DelayPOR(); /* wait for LCD power on to complete */
/* Force LCD to 8-bit mode */
LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK; /* set LCD data bits to zero */
LCD_D4_PIN = 1;
LCD_D5_PIN = 1;
LCD_E_Pulse();
LCD_Delay();
LCD_E_Pulse();
LCD_Delay();
LCD_E_Pulse();
LCD_Delay();
/* Set LCD to 4-bit mode */
LCD_PORT_OUT &= ~LCD_DATA_BITS_MASK; /* set LCD data bits to zero */
LCD_D5_PIN = 1;
LCD_E_Pulse();
LCD_Delay();
/* Initialize LCD mode */
LCD_WriteCmd(LCD_FORMAT);
/* Turn on display, Setup cursor and blinking */
LCD_WriteCmd(DOFF & CURSOR_OFF & BLINK_OFF);
LCD_WriteCmd(DON & CURSOR_OFF & BLINK_OFF);
LCD_WriteCmd(CLEAR_DISPLAY);
LCD_WriteCmd(SHIFT_CUR_LEFT);
/* Set first position on line one, left most character */
LCD_SetPosition(LINE_ONE);
}
/*
* Hook for printf
*/
void putch(char txData)
{
LCD_WriteData(txData);
}
/*
* Main application
*/
void main(void)
{
OSCCON = 0x7A; //set operating frequency to 16MHz
ANSELA = 0;
ANSELB = 0;
ANSELC = 0;
//pull up
OPTION_REGbits.nWPUEN = 0;
WPUAbits.WPUA2 = 1;
WPUAbits.WPUA4 = 1;
WPUAbits.WPUA0 = 1;
WPUAbits.WPUA1 = 0;
WPUAbits.WPUA3 = 0;
WPUAbits.WPUA5 = 0;
LCD_Init();
__delay_ms(100);
LCD_SetPosition(LINE_ONE);
printf("Hello");
/*
* Application loop
*/
for(;;)
{
}
}

LCD 4 bit communication with PIC16

I use a PIC16F690 for communication with my LCD. I got the following code from an example. The problem is that I want to use the 4 lower bits for my own outputs, but it always gets overwritten. The problem is, that I always overwrite the complete port. How can I only write the 4 upper bits without touching the first 4.
#define LCD_DATA PORTC
void lcd_write (unsigned char c)
{
__delay_ms(1);
LCD_DATA = ((c >>4) & 0x0F);
LCD_STROBE();
LCD_DATA = (c & 0x0F);
LCD_STROBE();
}
void lcd_init()
{
char init_value;
ANSEL= 0; //Disable analog pins on PORTA
init_value= 0x3;
LCD_RS= 0;
LCD_EN= 0;
__delay_ms(100);
__delay_ms(15); //wait 15ms after power is applied
LCD_DATA = init_value;
LCD_STROBE();
__delay_ms(10);
LCD_STROBE();
__delay_ms(10);
LCD_DATA =2; //4-bit mode
LCD_STROBE();
lcd_write(0x28); //Set interface length
lcd_write(0x0C); //Display On, Cursor On, Cursor Blink
lcd_clear(); //Clear Screen
lcd_write(0x6); //Set entry mode
}
Hope you guys can help me :)
Edit:
Thank you for your hints. Found following solution and works perfectly or do i miss something?
void lcd_write (unsigned char c)
{
__delay_ms(1);
if(((c >>4) & 1))
{
RC0 = 1;
}else
{
RC0 = 0;
}
if(((c >>4) & 2))
{
RC1 = 1;
}else
{
RC1 = 0;
}
if(((c >>4) & 4))
{
RC2 = 1;
}else
{
RC2 = 0;
}
if(((c >>4) & 8))
{
RC3 = 1;
}else
{
RC3 = 0;
}
//LCD_DATA = ((c >>4) & 0x0F);
LCD_STROBE();
//LCD_DATA = (c & 0x0F);
if(c & 1)
{
RC0 = 1;
}else
{
RC0 = 0;
}
if(c & 2)
{
RC1 = 1;
}else
{
RC1 = 0;
}
if(c & 4)
{
RC2 = 1;
}else
{
RC2 = 0;
}
if(c & 8)
{
RC3 = 1;
}else
{
RC3 = 0;
}
LCD_STROBE();
}
Unfortunately, your PIC model lacks LAT registers, which could allow you to write a cleaner and simplified code. If you had them, you could apply read-modify-write method. PIC18 and the latest PIC16 models have LAT registers.
If the uC has LAT registers, you can write it like this:
#define LCD_DATA LATC // Instead of PORTC
void lcd_write (unsigned char c)
{
__delay_ms(1);
unsigned char oldValue = LCD_DATA & 0xF0;
LCD_DATA = (oldValue | ((c >> 4) & 0x0F));
LCD_STROBE();
LCD_DATA = (oldValue | (c & 0x0F));
LCD_STROBE();
}
This may still work with PORTC, but it's risky to use it and it may be unreliable. Because reading from PORT register reads the current status of the port, not the output latch. But I suggest you to try it yourself and see the result. If there is sufficient time between the latch write accesses, the hardware pin output may have enough time to stabilize and it may work.

AVR Microcontrollers memory game

I am making a game where you need to repeat the sequence of LEDs that light up. This sequence is set by two LEDs. To repeat the sequence, I use the joystick.
I had an idea to make two bool arrays where True will indicate the left LED, and False will indicate the right LED. The first array must contain a random sequence(True/False) that needs to be repeated. When I push to one or the other side of the joystick, I want to write to the second array, respectively, True / False and all this time compare them.
This is what I have at the moment. (AT90USB647)
#define F_CPU 2000000UL
#include <avr/io.h>
#include <stdbool.h>
int main(void) {
MCUCR |= 0x80;
MCUCR |= 0x80;
DDRA = 0xFF;
PORTF = 0x20;
bool seq2[100];
while(1)
{
uint8_t x = PINF;
if(!(x & 0x20)) {
PORTA = 0x80;
}
else if(!(x & 0x08)) {
PORTA = 0x01;
}
else {
PORTA = 0x00;
}
}
}
The main question is how do I write True or False to an array when I push the joystick?
A basic approach could be:
#define F_CPU 2000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
volatile unsigned int counter;
static unsigned char pattern_position;
static unsigned char array_position;
static unsigned char pattern[] = {
0b01010101,
0b11010101,
0b10010101
};
ISR(TIMER0_COMPA_vect)
{
counter++;
}
int main(void)
{
MCUCR |= 0x80;
DDRA = 0xFF;
PORTF = 0x20;
// Timer initialization
// Mode: CTC
// Prescaler: 1024
TCCR0A = (1<<WGM01);
TCCR0B = (1<<CS02) | (1<<CS00);
// Calculate a correct time
//
// we want 1 ms -> f_TIMER0 = 1/T = 1/(1 * 10^-3)s = 1 kHz
//
// f_CPU f_CPU 20 MHz
// f_TIMER0 = ------------- -> OCR0A = ---------------- = ------------- = ~ 20 (It is not exactly 1ms but it is ok)
// k_H * OCR0A k_H * f_TIMER0 256 * 1 kHz
//
OCR0A = 20;
TIMSK0 = (1<<OCF0A); // Enable Timer0 Overflow Compare Match interrupt
// Show the sequence that the user should input
for (unsigned char i=0; i < sizeof(pattern)/sizeof(&pattern[0]); i++)
{
for (unsigned char j=0; j < 8; j +=2)
{
// There is possible a signal missing to show the user that the next pattern occurs!
PORTA = ((pattern[i]>>(j+1))<<PINA7) | ((pattern[i]>>j)<<PINA0);
// That the user can see the patterns a delay is necessary!
_delay_ms(1000);
}
}
// Signalize that the game starts
for (unsigned char i=0; i <8; i++)
{
PORTA ^= 0x81;
_delay_ms(1000);
}
TCNT0 = 0x00;
sei();
while(1)
{
// There is possible a signal missing to trigger next pattern input to the user!!!
if(!(PINF & (1<<PINF5)))
{
PORTA |= 0x80;
}
if(!(PINF & (1<<PINF3)))
{
PORTA |= 0x01;
}
// Time is 4 seconds to match the correct pattern
if(counter >= 4000)
{
if(!((pattern[pattern_position] & (1<<array_position)) == (0x01 & PORTA)))
{
// Wrong input end of game
}
array_position++;
if(!((pattern[pattern_position] & (1<<array_position)) == (0x01 & (PORTA>>8))))
{
// Wrong input end of game
}
array_position++;
if(array_position >= 8)
{
array_position = 0;
pattern_position++;
}
if(pattern_position >= (sizeof(pattern)/sizeof(&pattern[0])))
{
// End of game reached winning!
}
counter = 0x00;
PORTA = 0x00;
TCNT0 = 0x00;
}
}
}
I´m not sure if you are exactly trying this to do and i also can not test the code on your target platform but maybe this is a rudimental approach to solve your problem...

STM8L051F3 GPIO Initial Config

I am programming the STM8L051F3 processor for a simple application in which it is only necessary to control all GPIO.
The problem is that I can't control the GPIOC pin 0.
I just configured the GPIO registers. Is any other startup necessary?
I also tried to use stm8cubemx on Ubuntu. Software that I found useless because it generates an ioc8 file that has no information on how to use it in Ubuntu.
#include <stdint.h>
#include <string.h>
#include "stm8l.h"
void config_gpio(){
//76543210
PA_DDR = 0b00000000;
PA_CR1 = 0xff;
PA_CR2 = 0x00;
//76543210
PB_DDR = 0b00100110;
PB_CR1 = 0xff;
PB_CR2 = 0x00;
//76543210
PC_DDR = 0b01110011;
PC_CR1 = 0xff;
PC_CR2 = 0x00;
//76543210
PD_DDR = 0b00000000;
PD_CR1 = 0xff;
PD_CR2 = 0x00;
PA_ODR = 0x00;
PB_ODR = 0x00;
PC_ODR = 0x00;
PD_ODR = 0x00;
return;
}
void delay(unsigned long delay){
unsigned long i = 0;
for(i = 0; i < delay; i++) {}
return;
}
void rotate_left(int steps){
int n=0;
for(n=0; n<steps; n++){
//PC_DDR = 0b01110011;
//76543210
PC_ODR = 0b01100001;
delay(100);
PC_ODR = 0b00110001;
delay(100);
PC_ODR = 0b00010011;
delay(100);
PC_ODR = 0b01000011;
delay(100);
}
return;
}
void rotate_right(int steps){
int n=0;
for(n=0; n<steps; n++){
//PC_DDR = 0b01110011;
//76543210
PC_ODR = 0b01000011;
delay(100);
PC_ODR = 0b00010011;
delay(100);
PC_ODR = 0b00110001;
delay(100);
PC_ODR = 0b01100001;
delay(100);
}
return;
}
int main() {
config_gpio();
do {
delay(7777);
rotate_right(100);
rotate_left(100);
} while(1);
}
Terminal cmd.
Compile
sdcc -lstm8 -mstm8 --opt-code-size --std-sdcc99 --nogcse --all-callee-saves --debug --verbose --stack-auto --fverbose-asm --float-reent --no-peep -I./ -I./STM8S_StdPeriph_Driver/inc -D STM8L051 ./main.c
Prog
stm8flash -c stlinkv2 -p stm8l051f3 -s flash -w main.ihx
PC0 and PC1 only works as open drain in stm8l051f3.

Resources