I want to display letter on specific row and column in 16x2 LCD display with 8051 MCU. For Example:
Display "R" at 2nd column in first row
Display "W" at 3rd column in second row
I use these routines for the LCD:
#include<reg51.h>
/* Data pins connected to port P1 of 8051 */
#define Data_Port_Pins (P1)
sbit Register_Select_Pin = P2^0; /* Register Pin of LCD connected to Pin 0 of Port P2 */
sbit Read_Write_Pin = P2^1; /* Read/Write Pin of LCD connected to Pin 1 of Port P2 */
sbit Enable_Pin = P2^2; /* EN pin connected to pin 2 of port P2 */
/* Function for creating delay in milliseconds */
void Delay(unsigned int wait)
{
volatile unsigned i, j;
for(i = 0; i < wait; i++)
for(j = 0; j < 1200; j++);
}
/* Function to send command instruction to LCD */
void LCD_Command (unsigned char command)
{
Data_Port_Pins = command;
Register_Select_Pin =0;
Read_Write_Pin=0;
Enable_Pin =1;
Delay (2);
Enable_Pin =0;
}
/* Function to send display data to LCD */
void LCD_Data (unsigned char Data)
{
Data_Port_Pins = Data;
Register_Select_Pin=1;
Read_Write_Pin=0;
Enable_Pin =1;
Delay(2);
Enable_Pin =0;
}
/* Function to prepare the LCD and get it ready */
void LCD_Initialization()
{
LCD_Command (0x38);
LCD_Command (0x0e);
LCD_Command (0x01);
LCD_Command (0x81);
}
And this is my attempt:
Does it make any sense?
void LCD_Position( char row, char column)
{
unsigned char cmd = 0x80 ; /* Start address */
if( row != 0 ) /*If second row selected ...*/
{
cmd += 0x40 ; /*add start address of second row */
}
cmd += row & 0x0f ;
LCD_Command (cmd);
}
Refer to the data sheet for the LCD device in question. For the common 1602 type module (which the initialisation sequence shown suggests is what you are using) you set the position for the next data write using the Set DDRAM address instruction.
In 2-line display mode the 1st line starts at address 0x00, and the the 2nd line starts at 0x40.
void LCD_Position( int row, int pos)
{
LCD_Command( 0x80 | // Set DDRAM Address
(row == 0) ? 0x00 : 0x40 | // Row selector
(pos & 0x0f) ) ; // Position in row
}
Given (from the data sheet):
The code sets DB7 to 1 (0x80)indicating the Set DDRAM Addresss instruction. The other bits are address bits, but there are more locations in the display RAM than the width of the display, so only 0x00 to 0x0f and 0x40 to 0x4f refer to visible display locations. So if the second row is selected, 0x40 is masked in ((row == 0) ? 0x00 : 0x40), then the character position is masked in ((pos & 0x0f)). Although I have used bit-wise manipulation, the expression could equally be performed arithmetically:
0x80 + (row == 0) ? 0x00 : 0x40 + (pos & 0x0f)
In both cases the & 0x0f ensures the command is not modified and that the character is placed on the display even if the position if out-of-range.
Less succinctly, but perhaps easier to follow:
// Set DDRAM Address command - start of row 0
unsigned char cmd = 0x80 ;
// If second row selected ...
if( row != 0 )
{
// ... add start address of second row
cmd += 0x40 ;
}
// Add row offset. Masked to protect other
// bits from change if row is out of range.
cmd += row & 0x0f ;
// Write command
LCD_Command( cmd ) ;
Related
The assignment requires us to toggle ON LEDs if SW1 is pressed by using polling. I believe I am setting the direction of each port and reading the register correctly. However nothing happens when I press SW1. There is no way to debug and breakpoint the code while the code is running to see whats in the registers.
[HWGuide] states: [HWGuide]:http://ww1.microchip.com/downloads/en/DeviceDoc/doc8394.pdf
//LED0 = PR0 (PORTR PIN 0)
//LED1 = PR1 (PORTR PIN 1)
//SW1 = PF1 (PORTF PIN 1)
[Datasheet] states: [Datasheet]:http://ww1.microchip.com/downloads/en/DeviceDoc/atmel-8362-8-and-16bit-avr-microcontroller-atxmega256a3bu_datasheet.pdf
//PORTR starts at address = 0x07E0
//PORTF starts at address = 0x06A0
[Manual] states: [Manual]: http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-8331-8-and-16-bit-AVR-Microcontroller-XMEGA-AU_Manual.pdf
//Data Input Value register on I/O = (Addr) + 0x08 = 0x06A8 (PORTF)
Code:
#define PORTR *((volatile unsigned char *)0x7E0) /* I/O Port Register */
#define PORTF *((volatile unsigned char *)0x6A0) /* I/O Port Register */
#define PORTF_IN *((volatile unsigned char *)0x6A8) //PORTF Input Value Reg
#define PORTR_OUTTGL *((volatile unsigned char *)0x7E7) //LED Toggle Reg
#define ReadReg(port) (port)
#define WriteReg(port, value) (port = value)
int main(void)
{
//set PORTR direction
WriteReg(PORTR, 0xFF);
//set PORTF direction
WriteReg(PORTF, 0x00);
while(1)
{
if((ReadReg(PORTF_IN) == 0xFD)) //if PF1 = 0
{
WriteReg(PORTR_OUTTGL, 0x3); //toggle LEDs
{
{
}
I expect the register to read either (0x02)0000 0010 or the inverse (0xFD)1111 1101 and LEDs to turn on or off if the button is pressed.
Used bit manipulation to isolate the bit I was trying to poll for. Had no idea what the other bits could have been set to.
int main(void)
{
//set PORTR direction
WriteReg(PORTR, 0xFF);
//set PORTF direction
WriteReg(PORTF, 0xF9);
while(1)
{
char statusPF1 = (ReadReg(PORTF_IN) & 0x02) >> 1;
char statusPF2 = (ReadReg(PORTF_IN) & 0x04) >> 2;
if((statusPF1 == 0)) //if PF1 = 0
{
WriteReg(PORTR_OUTTGL, 0x01); //toggle LED0
_delay_ms(1000);
}
if((statusPF2 == 0)) //if PF2 = 0
{
WriteReg(PORTR_OUTTGL, 0x02); //toggle LED1
_delay_ms(1000);
}
if ((statusPF1 != 0) && (statusPF2 != 0))
{
_blinkLEDs();
}
}
}
I am having problem in receiving string from HC05 to ATmega16. I am able receive characters but not able to receive strings.
I want to control DC motor wirelessly using ATmega16 and Bluetooth module (HC05). I am sending the timer OCR1A values from serial monitor app to ATmega16 by HC05 but not succeeded.
#define F_CPU 16000000UL
#include<string.h>
#include <avr/io.h>
#include <util/delay.h>
#include <stdlib.h>
#include <stdio.h>
void UART_init()
{
UCSRB |= (1 << RXEN) | (1 << TXEN);
UCSRC |= (1 << URSEL) | (1 << UCSZ0) | (1 << UCS Z1);
UBRRL = 0x67;
}
unsigned char UART_RxChar()
{
while( (UCSRA & (1 << RXC)) == 0 );
return(UDR);
}
void UART_TxChar( char ch )
{
while( !(UCSRA & (1 << UDRE)) ); /* Wait for empty transmit buffer*/
UDR = ch ;
}
void UART_SendString( char* str )
{
unsigned char j = 0;
while( j <= 2 )
{
UART_TxChar( str[j] );
j++;
}
}
int main( void )
{
char buff[3];
char j;
int i = 0, k = 0;
DDRD = (1 << PD5);
UART_init();
while( 1 )
{
buff[0] = UART_RxChar();
buff[1] = UART_RxChar();
buff[2] = UART_RxChar();
j = UART_RxChar();
if( j == '!' )
{
UART_SendString( buff ); // this is to check whether the atmega16 received correct values for timer or not.
UART_SendString( "\n" );
}
}
}
The expected result is when I enter the number in serial monitor app, I should get back the same number on serial monitor app.
In the actual result I am getting different characters sometimes and empty some times.
The string buff is unterminated, so UART_SendString( buff ); will send whatever junk follows the received three characters until a NUL (0) byte is found.
char buff[4] = {0};
Will have room for the NUL and the initialisation will ensure that buff[3] is a NUL terminator.
Alternatively, send the three characters individually since without the terminator they do not constitute a valid C (ASCIIZ) string.
Apart from the lack of nul termination, you code requires input of exactly the form nnn!nnn!nnn!.... If the other end is in fact sending lines with CR or CR+LF terminators - nnn!<newline>nnn!<newline>nnn!<newline>... your receive loop will get out of sync.
A safer solution is to use the previously received three characters whenever a '!' character is received. This can be done in a number of ways - for long buffers a ring-buffer would be advised, but for just three characters it is probably efficient enough to simply shift characters left when inserting a new character - for example:
char buff[4] ;
for(;;)
{
memset( buff, '0', sizeof(buff) - 1 ) ;
char ch = 0 ;
while( (ch != '!' )
{
ch = UART_RxChar() ;
if( isdigit(ch) )
{
// Shift left one digit
memmove( buff, &buff[1], sizeof(buff) - 2 ) ;
// Insert new digit at the right
buff[sizeof(buff) - 2] = ch ;
}
else if( ch != '!' )
{
// Unexpected character, reset buffer
memset( buff, '0', sizeof(buff) - 1 ) ;
}
}
UART_SendString( buff ) ;
UART_SendString( "\n" ) ;
}
This also has the advantage that it will work when the number entered is less than three digits, and will discard any sequence containing non-digit characters.
I'm looking at the following code from STMicroelectronics on implementing USART communication with interrupts
#include <stm32f10x_lib.h> // STM32F10x Library Definitions
#include <stdio.h>
#include "STM32_Init.h" // STM32 Initialization
/*----------------------------------------------------------------------------
Notes:
The length of the receive and transmit buffers must be a power of 2.
Each buffer has a next_in and a next_out index.
If next_in = next_out, the buffer is empty.
(next_in - next_out) % buffer_size = the number of characters in the buffer.
*----------------------------------------------------------------------------*/
#define TBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
#define RBUF_SIZE 256 /*** Must be a power of 2 (2,4,8,16,32,64,128,256,512,...) ***/
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
#if TBUF_SIZE < 2
#error TBUF_SIZE is too small. It must be larger than 1.
#elif ((TBUF_SIZE & (TBUF_SIZE-1)) != 0)
#error TBUF_SIZE must be a power of 2.
#endif
#if RBUF_SIZE < 2
#error RBUF_SIZE is too small. It must be larger than 1.
#elif ((RBUF_SIZE & (RBUF_SIZE-1)) != 0)
#error RBUF_SIZE must be a power of 2.
#endif
/*----------------------------------------------------------------------------
*----------------------------------------------------------------------------*/
struct buf_st {
unsigned int in; // Next In Index
unsigned int out; // Next Out Index
char buf [RBUF_SIZE]; // Buffer
};
static struct buf_st rbuf = { 0, 0, };
#define SIO_RBUFLEN ((unsigned short)(rbuf.in - rbuf.out))
static struct buf_st tbuf = { 0, 0, };
#define SIO_TBUFLEN ((unsigned short)(tbuf.in - tbuf.out))
static unsigned int tx_restart = 1; // NZ if TX restart is required
/*----------------------------------------------------------------------------
USART1_IRQHandler
Handles USART1 global interrupt request.
*----------------------------------------------------------------------------*/
void USART1_IRQHandler (void) {
volatile unsigned int IIR;
struct buf_st *p;
IIR = USART1->SR;
if (IIR & USART_FLAG_RXNE) { // read interrupt
USART1->SR &= ~USART_FLAG_RXNE; // clear interrupt
p = &rbuf;
if (((p->in - p->out) & ~(RBUF_SIZE-1)) == 0) {
p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF);
p->in++;
}
}
if (IIR & USART_FLAG_TXE) {
USART1->SR &= ~USART_FLAG_TXE; // clear interrupt
p = &tbuf;
if (p->in != p->out) {
USART1->DR = (p->buf [p->out & (TBUF_SIZE-1)] & 0x1FF);
p->out++;
tx_restart = 0;
}
else {
tx_restart = 1;
USART1->CR1 &= ~USART_FLAG_TXE; // disable TX interrupt if nothing to send
}
}
}
/*------------------------------------------------------------------------------
buffer_Init
initialize the buffers
*------------------------------------------------------------------------------*/
void buffer_Init (void) {
tbuf.in = 0; // Clear com buffer indexes
tbuf.out = 0;
tx_restart = 1;
rbuf.in = 0;
rbuf.out = 0;
}
/*------------------------------------------------------------------------------
SenChar
transmit a character
*------------------------------------------------------------------------------*/
int SendChar (int c) {
struct buf_st *p = &tbuf;
// If the buffer is full, return an error value
if (SIO_TBUFLEN >= TBUF_SIZE)
return (-1);
p->buf [p->in & (TBUF_SIZE - 1)] = c; // Add data to the transmit buffer.
p->in++;
if (tx_restart) { // If transmit interrupt is disabled, enable it
tx_restart = 0;
USART1->CR1 |= USART_FLAG_TXE; // enable TX interrupt
}
return (0);
}
/*------------------------------------------------------------------------------
GetKey
receive a character
*------------------------------------------------------------------------------*/
int GetKey (void) {
struct buf_st *p = &rbuf;
if (SIO_RBUFLEN == 0)
return (-1);
return (p->buf [(p->out++) & (RBUF_SIZE - 1)]);
}
/*----------------------------------------------------------------------------
MAIN function
*----------------------------------------------------------------------------*/
int main (void) {
buffer_Init(); // init RX / TX buffers
stm32_Init (); // STM32 setup
printf ("Interrupt driven Serial I/O Example\r\n\r\n");
while (1) { // Loop forever
unsigned char c;
printf ("Press a key. ");
c = getchar ();
printf ("\r\n");
printf ("You pressed '%c'.\r\n\r\n", c);
} // end while
} // end main
My questions are the following:
In the handler function, when does the statement ((p->in - p->out) & ~(RBUF_SIZE-1)) ever evaluate to a value other than zero? If RBUF_SIZE is a power of 2 as indicated, then ~(RBUF_SIZE-1) should always be zero. Is it checking if p->in > p->out? Even if this isn't true, the conditional should evaluate to zero anyway, right?
In the line following, the statement p->buf [p->in & (RBUF_SIZE-1)] = (USART1->DR & 0x1FF); is made. Why does the code AND p->in with RBUF_SIZE-1?
What kind of buffer are we using in this code? FIFO?
Not so. For example, assuming 32-bit arithmetic, if RBUF_SIZE == 0x00000100 then RBUF_SIZE-1 == 0x000000FF and ~(RBUF_SIZE-1) == 0xFFFFFF00 (it's a bitwise NOT, not a logical NOT). The check you refer to is therefore effectively the same as (p->in - p->out) < RBUF_SIZE, and it's not clear why it is superior. ARM GCC 7.2.1 produces identical length code for the two (-O1).
p->in & (RBUF_SIZE-1) is the same as p->in % RBUF_SIZE when p->in is unsigned. Again, not sure why the former would be used when the latter is clearer; sure, it effectively forces the compiler to compute the modulo using an AND operation, but given that RBUF_SIZE is known at compile time to be a power of two my guess is that most compilers could figure this out (again, ARM GCC 7.2.1 certainly can, I've just tried it - it produces the same instructions either way).
Looks like it. FIFO implemented as a circular buffer.
I need to find the NAL header by parsing a RTP packet where each NAL unit is encapsulated into one RTP packet, then i parse the Nal header to know whether it's a PPS unit or not. I tried the following but i got no result:
dataBuffer = (char*)MESSAGE_ReturnPacket(msg);
byte * hdr = (byte*)dataBuffer + RTP_HDR_SIZE; //dataBuffer contains the RTP packet
RTPParsing((byte*)dataBuffer,rp,hdr);
if (rp.nal_type == 8 )
{
printf("\n PPS is found \n");
}
else
{
printf("\n No PPS is found\n");
}
where
int RTPParsing(byte *pData,RTPpacket_t &rp, byte *hdr)
{
if ((pData[0] & 0xc0) != (2 << 6)){
printf("[RTP] version is incorrect! dump = 0x%x 0x%x 0x%x 0x%x
\n",pData[0], pData[1], pData[2], pData[3]);
return 0;
}
/* parse RTP header */
rp.v = (pData[0] & 0xc0) >> 6; /* protocol version */
rp.p = (pData[0] & 0x40) >> 5; /* padding flag */
rp.x = (pData[0] & 0x20) >> 4; /* header extension flag */
rp.cc = (pData[0] & 0x0f); /* CSRC count */
rp.m = (pData[1] & 0x80) >> 7; /* marker bit */
rp.pt = (pData[1] & 0x7F); //Payload Type
rp.seq = ntohs (((unsigned short *) pData)[1]); /* sequence number */
rp.timestamp = ntohl (((unsigned int *) pData)[1]); /* timestamp */
rp.ssrc = ntohl (((unsigned int *) pData)[2]); /* synchronization source */
rp.nal_type = (hdr[1] & 0x1F); // get NAL unit's type
if (rp.cc)
{
for (int i = 0; i < rp.cc; i++)
{
//fprintf (out, " csrc: 0x%08x",ntohl (((unsigned int *) data)[3 + i]));
}
}
return 0;
}
Any help ?
According to RFC6184 in single NAL unit mode, the "The first byte of a NAL unit co-serves as the
RTP payload header"
You offset is incorrect (1 instead of 0):
rp.nal_type = (hdr[1] & 0x1F); // get NAL unit's type
Also, hard-coding RTP_HDR_SIZE as 12 (if that's what you're doing) could cause issues since the size of the header may vary based on extension headers, CSRCs, etc.
I am using a Renesas 16 bt MCU with HEW (High-performance Embedded Workbench) compiler.
The system receives ACSII data of the form:
<data><cc>
where <cc> comprises two ASCII hex digits corresponding to the 8-bit bitwise XOR of all the preceding characters. The maximum length of the string including <cc> is 14.
Here is my attempt:
#pragma INTERRUPT Interrupt_Rx0
void Interrupt_Rx0 (void)
{
unsigned char rx_byte, rx_status_byte,hex;
char buffer[15],test[5];
int r,k[15];
char * pEnd;
unsigned char dat,arr[14],P3;
unsigned int i,P1[10];
rx_byte = u0rbl; //get rx data
rx_status_byte = u0rbh;
if ((rx_status_byte & 0x80) == 0x00) //if no error
{
if ((bf_rx0_start == 0) && (rx_byte == '?') && (bf_rx0_ready == 0))
{
byte_rx0_buffer[0]=rx_byte;
bf_rx0_start = 1;
byte_rx0_ptr = 1;
}
else
{
if (rx_byte == '?')
{
bf_rx0_start = 1;
byte_rx0_ptr = 0;
}
if(bf_rx0_start == 1)
{
byte_rx0_buffer[byte_rx0_ptr++] = rx_byte;
sprintf(buffer,"%X",rx_byte); //ASCII CONVERSION
dat=strtol(buffer,&pEnd,16);
// P1=(int)dat;
// sprintf(P1,"%s",dat);
delay_ms(2000);
k[byte_rx0_ptr++]=dat;
}
if ((byte_rx0_ptr == 14))
bf_rx0_start = 0;//end further rx until detect new STX
}
}
}
convert this value to hexadec value & xor it ie(3F^30^31^53^52^57=68), if i can do this calculation in program
You fundamentally don't understand the difference between values and encodings. Two plus three is five whether you represent the two as "2", "two", or "X X". Addition operates on values, not representations. So to "convert to hexadecimal & xor it" makes no sense. You XOR values, not representations. Hexadecimal is a representation.
To maintain a running XOR, just do something like int running_xor=0; at the top and then running_xor ^= rx_byte; each time you receive a byte. It will contain the correct value when you are finished. Set it to zero to reset it.
Get hexadecimal completely out of your head. That is just how those values are being printed for your consumption. That has nothing to do with the internal logic of your program which deals only in values.
You would do well to separate out the data validation from the data reception, even to the extent that you don't do it in the interrupt handler; it is likely to be better to buffer the data in the ISR unchecked and defer the data validation to the main code thread or a task-thread if you are using an RTOS. You certainly don't want to be calling heavy-weight library functions such as sprintf() or strtol() in an ISR!
Either way, here is a function that would take a pointer to a received string, and its length (to avoid an unnecessary strlen() call since you already know how many characters were received), and returns true if the checksum validates, and false otherwise. It has no restriction on data length - that would be performed by the calling function.
If you know that your checksum hex digits will always be either upper or lower-case, you can simplify the decodeHexNibble() function.
#include <stdint.h>
#include <stdbool.h>
uint8_t decodeHexNibble() ;
uint8_t decodeHexByte( char* hexbyte ) ;
uint8_t decodeHexNibble( char hexdigit ) ;
bool checkData( char* data, int length )
{
int data_len = length - 2 ;
char* bcc_ptr = &data[data_len] ;
uint8_t rx_bcc_val = 0 ;
uint8_t actual_bcc_val = 0 ;
int i = 0 ;
// Convert <cc> string to integer
rx_bcc_val = decodeHexByte( bcc_ptr ) ;
// Calculate XOR of <data>
for( i = 0; i < data_len; i++ )
{
actual_bcc_val ^= data[i] ;
}
return actual_bcc_val == rx_bcc_val ;
}
uint8_t decodeHexNibble( char hexdigit )
{
uint8_t nibble ;
if( hexdigit >= '0' && hexdigit <= '9' )
{
nibble = hexdigit - '0' ;
}
else if( hexdigit >= 'a' && hexdigit <= 'f' )
{
nibble = hexdigit - 'a' + 10 ;
}
else if( hexdigit >= 'A' && hexdigit <= 'F' )
{
nibble = hexdigit - 'A' + 10 ;
}
else
{
// Do something 'sensible' with invalid digits
nibble = 0 ;
}
return nibble ;
}
uint8_t decodeHexByte( char* hexbyte )
{
uint8_t byte = hexbyte[0] << 4 ;
byte |= hexbyte[1] ;
return byte ;
}