I'm trying to connect 16*2 LCD and tm4c123gxl but It's not working - c

I tried to connect tm4c123gxl microcontroller with 16*2 LCD to print some letter. But some for some reason, my LCD does not work and only displays black boxes on the 1st row.
As you can see, I am using 3 pins of PORT A to connect RS, R/W, EN. And I use all 8 pins of PORT B to connect 7~14pins of LCD (data).
And this is the code I wrote on CCS
//rcgcgpio
#define RCGCGPIO (*((volatile unsigned long *) 0x400FE608))
//LCD
//PORTA 2,3,4
#define GPIODEN_PORTA (*((volatile unsigned long *) 0x4000451C))
#define GPIODIR_PORTA (*((volatile unsigned long *) 0x40004400))
#define GPIODATA_PORTA (*((volatile unsigned long*) 0x40004070))//1110000
//PORTB 0,1,2,3,4,5,6,7
#define GPIODEN_PORTB (*((volatile unsigned long *) 0x4000551C))
#define GPIODIR_PORTB (*((volatile unsigned long *) 0x40005400))
#define GPIODATA_PORTB (*((volatile unsigned long *) 0x400053FC))//11111111
//instruction, put this into portB
#define LCD_clear_display 0x1
#define LCD_return_home 0x2
#define LCD_display_shift_right 0x5
#define LCD_cursor_line1_position0 0x80
void LCD_setup();
void LCD_write_IR(unsigned char inst);
void LCD_write_DR(unsigned char data);
void Keypad_setup();
char Keypad_read();
void Delay(unsigned int t);
/**
* main.c
*/
int main(void)
{
LCD_setup();
LCD_write_IR(LCD_cursor_line1_position0);
LCD_write_IR(LCD_clear_display);
while(1){
LCD_write_DR('A');
}
}
void LCD_setup(){
RCGCGPIO |= 0x3;//000011 Port A and Port B
GPIODEN_PORTA |= 0x1C;//11100
GPIODIR_PORTA |= 0x1C;//11100
GPIODEN_PORTB |= 0xFF;//11111111
GPIODIR_PORTB |= 0xFF;//11111111
}
void Delay(unsigned int t){//ms delay
int i;
int j;
for(i=0;i<t;i++){
for(j=0;j<16000;++j){
}
}
}
void LCD_write_IR(unsigned char inst){
GPIODATA_PORTA = 0x10;//EN:1, R/W:0, RS:0, 0, 0
GPIODATA_PORTB = inst;
Delay(2);
/*
if(inst < 4){//clear display
Delay(2);
}else{
Delay(1)//entry mode set
}
*/
}
void LCD_write_DR(unsigned char data){
GPIODATA_PORTA = 0x14;//10100
GPIODATA_PORTB = data;
Delay(2);
}
Unfortunately, LCD is not working just like this picture
What I should do to print some letter on the LCD?

Related

How can implement delay function with systick in arm processor and make it work in over flow ,the load register is 32 bit

#include"SYSTICK.h"
volatile u32 DELAY;
void SYS_INIT(){
STCTRL =0x0;
STRELOAD =16000000-1; //time for 1s
STCURRENT=0x0;
STCTRL =0x07;
}
void SYS_DELAY(u32 TIME_S){
DELAY = 0;
while(DELAY > TIME_S);
}
void SysTick_Handler(){
DELAY++;
}
#include "GBIO_INIT.h"
#include "USER_INTERFACE.h"
#include "SYSTICK.h"
#define RCGCGPIO *((unsigned int *) 0x400FE608)
int main(void){
/*Enabling clock for GPIO PORTF*/
RCGCGPIO |= (0x20);
SYS_INIT();
while(1){
GPIO_SetPinDirection(SELECTED_PORT,SELECTED_PIN_Input, GPIO_INPUT);
GPIO_SetPinDigEnable(SELECTED_PORT,SELECTED_PIN_Input, GPIO_DEN_SET);
GPIO_SetPinCurrent(SELECTED_PORT,SELECTED_PIN_Input, PORT_BIN_CUR_2MA);
GPIO_SetPinInternalAttach(SELECTED_PORT,SELECTED_PIN_Input, PORT_BIN_PUR);
u8 x =GBIO_ReadPinValeu(SELECTED_PORT,SELECTED_PIN_Input);
GPIO_SetPinDirection(SELECTED_PORT,SELECTED_PIN_OUTPUT,GPIO_OUTPUT);
GPIO_SetPinValue(SELECTED_PORT,SELECTED_PIN_OUTPUT, x);
SYS_DELAY(3);
GPIO_SetPinValue(SELECTED_PORT,SELECTED_PIN_OUTPUT, STD_LOW);
SYS_DELAY(5);
}
}

ADC interrupt not getting called

I want ADC Interrupt Service Routine to be called after each End of Conversion. However it is not being called.
Here's is my code:
#define RCC_APB2ENR (*((volatile unsigned long*) 0x40021018))
#define ADC1_CR1 (*((volatile unsigned long*) 0x40012404))
#define ADC1_CR2 (*((volatile unsigned long*) 0x40012408))
#define ADC1_SMPTR2 (*((volatile unsigned long*) 0x40012410))
#define ADC1_SQR1 (*((volatile unsigned long*) 0x4001242C))
#define ADC1_SQR3 (*((volatile unsigned long*) 0x40012434))
#define ADC1_DR (*((volatile unsigned long*) 0x4001244C))
#define NVIC_SETENA_0 (*((volatile unsigned long*) 0xE000E100))
#define NVIC_CLRENA_0 (*((volatile unsigned long*) 0xE000E180))
volatile short conversionResult = -1;
void ADC_IRQHandler(void) // ADC Interrupt service routines
{
if((ADC1_CR2 & 0x00000002) == 0x00000002) // check if EOC bit set
conversionResult = ADC1_DR;
else
conversionResult = -1;
}
void ADC_Init(short mode)
{
// enable ADC Interrupts
NVIC_SETENA_0 |= 0x00040000;
// enable clock for ADC_1
RCC_APB2ENR |= 0x0000200;
ADC1_CR2 &= 0x00000000; // resetting controll registers
ADC1_CR1 &= 0x00000000;
ADC1_CR1 |= 0x00000020; // EOC interrupt enable
if(mode == 1) // continous mode
ADC1_CR2 |= 0x00000002;
ADC1_CR2 |= 0x00000001; // Waking up from power Down State
// Perfroming Calibration
ADC1_CR2 |= 0x00000004;
while((ADC1_CR2 & 0x00000004) != 0);
}
void ADC_ChannelConfig(short channelNumber, short sampleTime)
{
//selecting channel
ADC1_SQR3 |= channelNumber;
//setting sample time for this channel
int temp = sampleTime;
temp = (temp << channelNumber * 3);
ADC1_SMPTR2 |= temp;
}
void ADC_StartConversion()
{
ADC1_CR2 |= 0x00000001; // enable adc again to start conversion
}
int main(void)
{
ADC_Init(0);
ADC_ChannelConfig(2, 3);
ADC_StartConversion();
while(1)
{
}
return (1);
}
Here's the disassembly after the interrupt occurs,
I tried changing
void ADC_IRQHandler(void)
to,
void ADC1_IRQHandler(void)
but it still didn't worked.
The Micro-controller I am using is STM32F103RB. Thanks!
Found the problem.
The ADC ISR was,
void ADC1_2_IRQHandler(void)
This ISR is called for both ADC 1 and ADC 2.

5 years later - NXP ADCs aren't working

Some time ago I was trying to programm the ADC on the NXP's LPC3143 withouth sucess. Now 5 years later I buy myself an LPC4088 Quick start board and try it with LPC4088. And again the same problem persists with ADC! I just can't seem to make it work while I/O config, GPIO, timers and PWM work like a charm...
I am always programming MCU's by reading the user manual. So after reading the manual this is what I came up with:
LPC4088-ioconfig.h
//register definitions for IOCONFIG peripheral
//this one is "type A"
#define IOCON_P1_31 (*((volatile unsigned int *) 0x4002C0FC))
LPC4088-system.h
//register definitions for system & clock peripheral
//used to turn on peripherals
#define PCONP (*((volatile unsigned int *) 0x400FC0C4))
LPC4088-gpio.h
//register definitions for GPIO peripheral
//only port 1
#define DIR1 (*((volatile unsigned int *) 0x20098020))
#define MASK1 (*((volatile unsigned int *) 0x20098030))
#define PIN1 (*((volatile unsigned int *) 0x20098034))
#define SET1 (*((volatile unsigned int *) 0x20098038))
#define CLR1 (*((volatile unsigned int *) 0x2009803C))
LPC4088-adc.h
//register definitions for ADC peripheral
#define CR (*((volatile unsigned int *) 0x40034000))
#define GDR (*((volatile unsigned int *) 0x40034004))
#define INTEN (*((volatile unsigned int *) 0x4003400C))
#define DR0 (*((volatile unsigned int *) 0x40034010))
#define DR1 (*((volatile unsigned int *) 0x40034014))
#define DR2 (*((volatile unsigned int *) 0x40034018))
#define DR3 (*((volatile unsigned int *) 0x4003401C))
#define DR4 (*((volatile unsigned int *) 0x40034020))
#define DR5 (*((volatile unsigned int *) 0x40034024))
#define DR6 (*((volatile unsigned int *) 0x40034028))
#define DR7 (*((volatile unsigned int *) 0x4003402C))
#define STAT (*((volatile unsigned int *) 0x40034030))
#define TRM (*((volatile unsigned int *) 0x40034034))
main.c
#include "LPC4088-ioconfig.h"
#include "LPC4088-system.h"
#include "LPC4088-gpio.h"
#include "LPC4088-adc.h"
int main(){
//***********************************************************
//we set P1.13 (port 1, pin 13) as GPIO, no pull-up, no hysteresis, not inverted, standard, push-pull
IOCON_P1_13 &= !(0x67F);
//we turn on GPIO peripheral
PCONP |= (1<<15);
//set P1.13 as an output GPIO
DIR1 |= (1<<13);
//setting a mask for pin P1.13
MASK1 &= !(1<<13);
//***********************************************************
//configure pin P1.31 as an input ADC0_IN5 (channel 5)
IOCON_P1_31 |= 0b011;
//we disable pullup or pulldown resistors on pin P1.31
IOCON_P1_31 &= !(0x3<<4);
//we configure pin P1.31 for ADMODE
IOCON_P1_31 &= !(1<<7);
//we turn on the ADC peripheral
PCONP |= (1<<12);
//we divide PCLK delimo with 99+1=100 (only for precaution)
CR |= (99<<8);
//we start the ADC
CR |= (1<<21);
//we disable ADC interrupts
INTEN &= !(0x1FF);
//we choose chanel 5 which is the only one that we choose
CR &= !(0xFF);
CR |= (1<<5);
//before choosing "burst mode" we need to turn off the conversion
CR &= !(0x7<<24);
//we choose "burst mode" - conversion starts and is continuous
CR |= (1<<16);
//***********************************************************
while(1){
//we wait for the conversion to finish and we save the result
//we right-shift because value is stored in DR5 bits 15:4!
while( (DR5 & (1<<31) ) != (1<<31) );
int result = ( (DR5 & 0xFF0) >> 4);
//12-bit has a max value of 0xFFF - we compare result to the half of this value - 0x7FF.
if (result >= 0x7FF){
//turn on an LED on pin P1.13
SET1 |= (1<<13);
}
else{
//turn off an LED on pin P1.13
CLR1 |= (1<<13);
}
}
}
Here is also a more detailed interface description for LPC4088 Quick start board - my external potentiometer output is connected to the P1.31, while the LED is already embedded onto the board:
Ok so I worked my ass off for this one for 10 hours straigth and went to bed at 4:30 in the morning... And here it is - the working example for LPC4088 ADC (header files are the same as in the question):
#include "LPC4088-ioconfig.h"
#include "LPC4088-system.h"
#include "LPC4088-gpio.h"
#include "LPC4088-adc.h"
int main(){
IOCON_P1_13 &= !(0x67F);
IOCON_P1_31 |= 0b011;
IOCON_P1_31 &= !(0b11<<4);
IOCON_P1_31 &= !(1<<7);
IOCON_P0_23 |= 0b011;
IOCON_P0_23 &= !(0b11<<4);
IOCON_P0_23 &= !(1<<7);
PCONP |= (1<<15);
DIR1 |= (1<<13);
MASK1 &= !(1<<13);
PCONP |= (1<<12);
INTEN &= !(0x1FF);
CR &= !(0x7<<24);
CR &= !(1<<16);
while(1){
CR |= (1<<21);
CR |= (0x1<<24);
while( (STAT & (1<<0) ) == 0x0 );
CR &= !(0x1<<24);
unsigned int result = 0;
result = ( (DR0 & 0xFFF0) >> 4);
CR &= (1<<21);
if (result > 0x7FF){
SET1 |= (1<<13);
}
else{
CLR1 |= (1<<13);
}
}
}
Much simpler that examples from LPC-Open. And I bet this will be helpful to some of you guys... I intend to open my GIT with examples like these for all of the peripherals. But now I only know how to manipulate ioconfig, gpio, timer, pwm and adc.

AVR, UART, Proteus simulation, not all data displayed on virtual terminal

I am writing a code for a MCU until that will transmit data via UART (RS232).
[ATmega8A]
Currently, I am testing my code in Proteus:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
#include <compat/twi.h>
#define FOSC 16000000 //Clock Speed
#define BAUD 9600 //Baud rate set to 9600
#define MYBRR FOSC/16/BAUD-1
void USART_Init (void)
{
UBRRH = (MYBRR >> 8); //Code for setting
UBRRL = MYBRR; //the baud rate
UCSRB = (1 << RXEN) | (1 << TXEN); //Enable receiver and transmitter
UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); //Frame format setting: 8 Data, 2 Stop bit
}
/* USART transmit function */
void USART_Transmit(unsigned char data)
{
while(!(UCSRA & (1 << UDRE))); //Wait until transmit buffer is empty
UDR = data;
}
/* USART receive function */
unsigned char USART_Receive(void)
{
while(!(UCSRA & (1 << RXC))); //Wait until data is received
return UDR; //Get the data from buffer and return it
}
and the test code in main:
int main(void)
{
unsigned char c;
while(1)
{
a = USART_Receive();
c = 10;
USART_Transmit(c);
_delay(10000);
}
}
In Proteus, the virtual terminal displays 0. However, I am expecting to see 10.
This is just one example, in general only the last digit/character is getting displayed on the virtual terminal.
I cannot explain this. Proteus bug or logic error?
Thank you for any advise.
UART data is sent only in ascii format...you have to convert the integer data to ascii format..use itoa() or do this one
int main(void)
{
unsigned char c;
unsigned char b;
while(1)
{
a = USART_Receive();
c = 10;
b=c;
b=c/10;
USART_Transmit(b+48);
b=0;
b=c%10;
USART_Transmit(b+48);
_delay(10000);
}
}

LCD shift right and shift left bugs

I have made a library for LCD with HD44780 controller in it, and from the datasheet I read that the code 0x18 will shift the entire display one position to the left, but when I made that, the display disappears.
I have also read that 0x1C shifts the entire display one position to the right but when I made it, the entire display shifts to left.
My code:
/*
* main.c
*
* Created: 11/14/2013 7:54:02 PM
* Author: A R M T
*/
#include <avr/io.h>
#define F_CPU 1000000UL
#define __DELAY_BACKWARD_COMPATIBLE__
#include <util/delay.h>
#define LCD_DPRT PORTA //LCD DATA PORT
#define LCD_DDDR DDRA //LCD DATA DDR
#define LCD_DPIN PINA //LCD DATA PIN
#define LCD_CPRT PORTB //LCD COMMANDS PORT
#define LCD_CDDR DDRB //LCD COMMANDS DDR
#define LCD_CPIN PINB //LCD COMMANDS PIN
#define LCD_RS 0 //LCD RS
#define LCD_RW 1 //LCD RW
#define LCD_EN 2 //LCD EN
//*************************************************************
void delay_us(unsigned int d);
void lcdCommand(unsigned char cmnd);
void lcdData(unsigned char data);
void lcd_init(void);
void lcd_gotoxy(unsigned char x, unsigned char y);
void lcd_print(char *str);
//*************************************************************
void delay_us(unsigned int d)
{
_delay_us(d);
}
//*************************************************************
void lcdCommand(unsigned char cmnd)
{
LCD_DPRT = cmnd; //send cmnd to data port
LCD_CPRT &= ~(1<<LCD_RS); //RS = 0 for command
LCD_CPRT &= ~(1<<LCD_RW); //RW = 0 for write
LCD_CPRT |= (1<<LCD_EN); //EN = 1 for H-to-l pulse
delay_us(1); //Wait to make enable wide
LCD_CPRT &= ~(1<<LCD_EN); //EN = 1 for H-to-l pulse
delay_us(100); //Wait to make enable wide
}
//*************************************************************
void lcdData(unsigned char data)
{
LCD_DPRT = data; //send data to data port
LCD_CPRT |= (1<<LCD_RS); //RS = 1 for data
LCD_CPRT &= ~(1<<LCD_RW); //RW = 0 for write
LCD_CPRT |= (1<<LCD_EN); //EN = 1 for H-to-L pulse
delay_us(1); //wait to make enable wide
LCD_CPRT &= ~(1<<LCD_EN); //EN = 0 for H-to-L pulse
delay_us(100); //wait to make enable wide
}
//*************************************************************
void lcd_init(void)
{
LCD_DDDR = 0xFF;
LCD_CDDR = 0xFF;
LCD_CPRT &= ~(1<<LCD_EN); //LCD_EN = 0
delay_us(15000); //wait for init
lcdCommand(0x38); //init. LCD 2 line, 5 * 7 matrix
lcdCommand(0x0E); //display on, cursor on
lcdCommand(0x01); //clear LCD
delay_us(2000); //wait
lcdCommand(0x06); //shift cursor right
}
//*************************************************************
void lcd_gotoxy(unsigned char x, unsigned char y)
{
unsigned char firstCharAdr[] = {0x80, 0xC0, 0x94, 0xD4};
lcdCommand(firstCharAdr[y-1] + x - 1);
delay_us(100);
}
//*************************************************************
void lcd_print(char *str)
{
unsigned char i = 0;
while (str[i] != 0)
{
lcdData(str[i]);
i++;
}
}
//*************************************************************
int main(void)
{
lcd_init();
lcd_gotoxy(1,1);
lcd_print("Armia");
lcd_gotoxy(1,2);
lcd_print("Wagdy");
_delay_ms(1000 / 2);
lcdCommand(0x18); // Shift the entire display one position to the left
while(1);
return 0;
}
I meant that when I burned this code I excepected that aftr(1000 / 2) ms this output will shift to left
but what appears was(the word disappears instead of shifting left one postition)
Can any one help me in that problem please?!
I tried your code in proteus version 7.10 and shift left works fine
Note that you are using the _delay_us function with a variable parameter, that is not the correct way, it gives wrong delays and generates big hex file because it forces the float library to be included
delay.h manual
Note:
In order for these functions to work as intended, compiler optimizations must be enabled, and the delay time must be an
expression that is a known constant at compile-time. If these
requirements are not met, the resulting delay will be much longer (and
basically unpredictable), and applications that otherwise do not use
floating-point calculations will experience severe code bloat by the
floating-point library routines linked into the application.
Replace the code with a loop that calls the delay several times
while (d--)
{
_delay_ms(1);
}

Resources