Could not call the sub-routine correctly Microcontroller PIC18F - c

I have a project to program a microcontroller PIC18F, I have to connect a switching circuit to the microcontroller board, this switching circuit has an electric lock and a buzzer to be connected to it.
The lock is initially powered. It is supposed that when I send '1', the buzzer will be powered with a square wave and the lock will be powered off. When it receives '0', the buzzer will be switched off without powering the lock again. When it receives '2' the lock should be powered but if the buzzer was unpowered before, it should not be powered again.
My confusion is in the last part. When I send '2' via the hyperterminal, and I sent '0' before it, the buzzer is powered again.
Here is the code,
void buzzertest();
char uart_rd;
int buzzer;
void main() {
TRISB=0X00;
PORTB=0x00;
RB5_bit = 0xFF; //lock open
UART1_Init(9600); // Initialize UART module at 9600 bps
while (1) { // Endless loop
if (UART1_Data_Ready()) // If data is received,
{
buzzer=1;
uart_rd = UART1_Read(); // read the received data,
if(uart_rd =='1') {
RB5_bit = 0x00; //lock closed
buzzertest();
}
if(uart_rd =='0' ){ //disable buzzer
RB1_bit = 0x00; //buzzer
buzzer=0;
}//end if
buzzer=0;
if(uart_rd =='2'){ //disable lock
RB5_bit=0xFF;
if(buzzer!=1){
buzzertest();
}
}//end if
} //end outer if
} //end while
}//end main
void buzzertest(){
while(1){
RB1_bit = 0xFF; //buzzer
Delay_ms(1000);
RB1_bit = 0x00; //buzzer
Delay_ms(1000);
if (UART1_Data_Ready())
break;
}//end while loop
}
Can please anyone help me solving this?

You're setting buzzer to 0 outside the if(uart_rd='0') block. So when you come to the if(uart_rd='2') block, buzzer is always 0 and so the if(buzzer!=1) block is always called.
Have you tried stepping through this with a debugger? It would show up this kind of thing easily. You could also change those if blocks either to a switch statement or a series of if / else if statements to avoid these sorts of issues.

here is the running code:
void buzzertest();
char uart_rd;
int buzzer;
void main() {
TRISB=0X00;
PORTB=0x00;
RB5_bit = 0xFF; //lock open
UART1_Init(9600); // Initialize UART module at 9600 bps
while (1) { // Endless loop
if (UART1_Data_Ready()) // If data is received,
{
uart_rd = UART1_Read(); // read the received data,
if(uart_rd =='1') {
RB5_bit = 0x00; //lock closed
buzzertest();
buzzer=1 ;
}
else if(uart_rd =='0' ){ //disable buzzer
RB1_bit = 0x00; //buzzer
buzzer=0;
}//end else if
else if(uart_rd =='2'){ //disable lock
RB5_bit=0xFF;
if(buzzer==1){
buzzertest();
}
}//end else if
} //end outer if
} //end while
}//end main
void buzzertest(){
while(1){
RB1_bit = 0xFF; //buzzer
Delay_ms(1000);
RB1_bit = 0x00; //buzzer
Delay_ms(1000);
if (UART1_Data_Ready())
break;
}//end while loop
}

Related

SPI Communication between ATMEGA 324PB and Arduino Nano

Here I'm trying to Send the SPI command from the master (Arduino Nano) to the slave(ATMEGA324PB).
First Master receives a command from the serial monitor. When the serial message receives completely, the Master passes the message to the Slave. Whenever the slave has a message to send, it will interrupt the Arduino nano using pin 3. However, in the first round slave send messages to master, and master can read it successfully. But in the second round It couldn't happen. I was unable to find the issue. I will attach the codes below.
User message is like in this manner XF01600#.
Send X (or Y)
Send F (or B)
Send 01600
Send #
This is my Master Code :
` #include <SPI.h>`
char Direction;
char Axis;
char TxCommand;
char TxEnd;
bool stringComplete = false; // Is receive complete ?
bool TxComplete=false;
int k=0;
int j=0;
String StepCount;
SPISettings setting(200000,MSBFIRST,SPI_MODE0);
void setup() {
Serial.begin(9600);
pinMode(10,OUTPUT);
pinMode(9,OUTPUT);
pinMode(2,OUTPUT);
attachInterrupt(digitalPinToInterrupt(3),SlaveReceive,RISING);
SPI.begin();
}
void SlaveReceive(){
SPI.begin();
SPI.beginTransaction(setting);
digitalWrite(10,LOW);
TxCommand=SPI.transfer(0xFF);//dummy
TxEnd=SPI.transfer(0xFF);//dummy
digitalWrite(10,HIGH);
SPI.endTransaction();
Serial.print("Received Command-");
Serial.println(TxCommand );
Serial.print("Received End-");
Serial.println(TxEnd);
if(TxEnd=='~'){
TxComplete=true;
}
}
void SPI_Transfer(){
SPI.transfer(Direction);//transfer direction
delay(5);
SPI.transfer(StepCount.length());//transfer incoming step length
delay(5);
for(int i=0;i<StepCount.length();i++){//transfer step count;
SPI.transfer(StepCount[i]);
Serial.println(StepCount[i]);
delay(5);
}
SPI.transfer('#');
delay(5);
}
void loop() {
if (stringComplete) {
if(Direction=='F'){
digitalWrite(2,HIGH);
}
else if(Direction=='B'){
digitalWrite(2,LOW);
}
Serial.print("Direction-");
Serial.println(Direction);
Serial.println(StepCount);
Serial.println(StepCount.length());
SPI.beginTransaction(setting);
if(Axis=='X'){ // Chip Select line for X axis driver is pin 10;
digitalWrite(10,LOW);
SPI_Transfer();
digitalWrite(10,HIGH);
}
else if(Axis=='Y'){ /// Chip select line for Y axis driver is pin 9;
digitalWrite(9,LOW);
SPI_Transfer();
digitalWrite(9,HIGH);
}
SPI.endTransaction();
stringComplete = false;
k=0;
}
if(TxComplete){
if(TxCommand=='S'){
digitalWrite(2,LOW);
TxComplete=false;
}
}
}
void serialEvent() {
while (Serial.available()>0) {
if(k==0){
Axis = Serial.read();
k++;
}
else if(k==1){
Direction=Serial.read();
k++;
}
else if(Serial.read()!='#'){
//StepCount[k-1]=Serial.readString();
StepCount=Serial.parseInt();
k++;
}
else{
stringComplete = true;
}
}
}
Slave Main Command :
while(1){
if(SPI_RECEIVE_COMPLETE){
SPI_RECEIVE_COMPLETE=false;
PORTA |=(1<<4);
Decode_SPI_Command();
switch (SPI_Command)
{
case 'F':
_Run_Motor(SPI_Data, true, 1, 0.3);//10 CYCLE
SlaveSendData(0x53);//S
break;
case 'B':
_Run_Motor(SPI_Data, false, 1, 0.3);
SlaveSendData(0x53);//S
break;
}
for(uint8_t i=0;i<15;i++){
SPI_Received_Data[i]=0;
}
SPI_Data=0;
SPI_BYTES_Transfer=0;
}
PORTA &=~(1<<4);
}
The Slave data send function:
void SlaveSendData(uint8_t SlaveCommand){
SPI_BYTES_Transfer=0;
SPI_Data_TX=true;
SPDR1=SlaveCommand;
SPI_Transmit_Data[0]=0x7E;//~
PORTA |=(1<<3);
_delay_ms(10);
PORTA &=~(1<<3);
}
Slave SPI interrupt function:
ISR(SPI1_STC_vect){
if(SPI_Data_TX){//slave is transmitting data
SPDR1 = SPI_Transmit_Data[SPI_BYTES_Transfer];
SPI_BYTES_Transfer++;
if(SPI_Received_Data[SPI_BYTES_Transfer-1]=='~'){
SPI_Data_TX=false;
//SPDR1=0x00;
SPI_BYTES_Transfer=0;
}
}
else{
SPI_Received_Data[SPI_BYTES_Transfer] = SPDR1;
SPI_BYTES_Transfer++;
if(SPI_Received_Data[SPI_BYTES_Transfer-1]=='#'){
SPI_RECEIVE_COMPLETE=true;
SPDR1=0x00;
}
}
}
Here I have found that in the else part SPI_RECEIVE_COMPLETE=true; never occurs on the second try. But I couldn't find where the issue is..?
serial monitor
Arduino Serial Monitor
Could you please take a look, Thank you.

System Hangs by writing delay after Timer_init()

I am facing a strange issue while programming PIC18f45k22. I am initiating system modules and then I write a blocking delay for 3 seconds to wait for a touch screen to start (because I need to send some information to this screen). But when I do this I discovered that when I initiate timer before writing the delay, I discover that the system freezes.
This is the code that I used
NOTE: all the functions work fine without any problem.
void main(void) {
Sys_Init();
__delay_ms(3000);
while(1){
//Code
}
System initiation code
void Sys_Init(void) {
Delay_XTAL();
OSCILLATOR_Init();
DIGITAL_PIN_STATE();
ANALOG_PIN_STATE();
ADC_INIT(); //change clock select pins when oscillator changes
Spi_Init();
DHT22_init();
Uart_Init(9600); //initiate UART (change baud values when oscillator value changed)
Timer1_Init(); //initiate timer one (change prescaler and counter value if oscillator value changes)
}
Timer code
void Timer1_Init(void){ //for interrupt program use this function
//Prescaler 1:1; TMR1 Preload = 61536; Actual Interrupt Time : 1 ms
T1CON = 0x01;
TMR1IF = 0;
TMR1H = 0xF0;
TMR1L = 0x60;
TMR1IE = 1;
INTCON = 0xC0;
}
Interrupt code
void __interrupt() ISR (void){
Timer1();
}
void Timer1(void){ //for interrupt program
if (TMR1IF){
cnt1++;
TMR1H = 0xF0; //overflow every 1 ms
TMR1L = 0x60;
TMR1IF = 0;
}
}

How to end external Interrupt Service Routine (ISR) in 8051

I wrote a simple led blinking code with hardware interrupt 0 of 8051.
When button is pressed it goes into interrupt service routine (ISR). After executing it should come back in main function but it is not coming.
This is my c code. Any positive reply will be appreciated.
sbit LED = P1^0;
void delay(int ms)
{
int i;
for(i=0;i<ms;i++)
{
TMOD = 0x01;
TH0 = 0xFC;
TL0 = 0x66;
TR0 = 1;
while(TF0==0);
TR0 = 0;
TF0 = 0;
}
}
void main(void)
{
P1 = 0x00;
/// P3 = 0x04;
IT0 = 1;
EX0 = 1;
EA = 1;
LED=1;
while(1)
{
LED=~LED;
delay(200);
}
return ;
}
void external0_isr() interrupt 0
{
EA=0;
LED =0 ;
delay(2000);
LED=1;
EX0=1;
EA=1;
return;
}
When you enter the button interrupt, you disable global interrupt EA=0;
That also disables the timer interrupt. Therefore, you program would hang at while(TF0==0) in your delay(2000) routine.

Can only read once from PIC16's RCO port

Been searching for an answer for this for a few days now. I'm trying to create this simple verification program where if I push a button it drives the voltage on RC0 to 5 volts, and when the button is unpushed, a pulldown resistor pulls the pin down to 0. The problem is, the code will only work the first time I push the button. After that it will not enter the if (RC0 == 1) loop. Here is my code snippet. What am I missing here?
void main(void){
/* Configure the oscillator for the device */
ConfigureOscillator();
/* Initialize I/O and Peripherals for application */
InitApp();
TRISB = 0x0F; // turn on RB7 for use as output
TRISC = 0xFF; // turn on RC0 for use as input
ANSEL = 0b11101111; // use RC0 as digital input
unsigned char time = 0;
while (1) {
//delay for 10 seconds
if (PORTCbits.RC0 == 1) {
while (time < 10) {
/* TODO */
RB7 = 1;
__delay_ms(100);
RB7 = 0;
__delay_ms(100);
time++;
}
}
if (PORTCbits.RC0 == 0){ //This if statement will always execute when
//RC0 == 0, but will not execute when I push
//the button. This really confuses me.
//Can RCO be given a value different than 1?
__delay_ms(2000);
}
RB7 = 0;
__delay_ms(500);
RB7 = 1;
__delay_ms(500);
}
}

Configuring UART1 in lpc 2468

I am working on lpc2468 ARM-based microcontroller. I am not able to configure the UART1 of the controller. Previously I was using UART0 for the same purpose, but due to some changes in hardware now I have to use UART1.
I want to connect GPRS module (SIMCOM 300) to the UART1 of the microcontroller. Here's my code so far:
void init_serial_gprs (void){
PINSEL7 |= 0x0000000F;
U1LCR = 0x00000080;
U1DLL = 0x00000041;
U1DLM = 0x00000000;
U1LCR = 0x03;
VICVectAddr7 = (unsigned)serial1_isr;
VICIntEnable = 1 << 7;
SBUF= U1RBR;
U1IER = 3;
}
void serial1_isr(void) __irq {
volatile char dummy;
volatile UWORD32 IIR1;
/*------------------------------------------------
Repeat while there is at least one interrupt source.
------------------------------------------------*/
while (((IIR1 = U1IIR) & 0x01) == 0)
{
switch (IIR1 & 0x0E)
{
case 0x06: /* Receive Line Status */
dummy = U1LSR; /* Just clear the interrupt source */
break;
case 0x04: /* Receive Data Available */
case 0x0C: /* Character Time-Out */
SBUF= U1RBR;
if(genflag.fl_m_psw || new_st == 0 ||new_st == 0x1f){
if(genflag.gprs_con) receive_data();
else
receive_data_gprs();
}
break;
case 0x02: /* THRE Interrupt */
if(genflag.gprs_con) transfer_data();
else transfer_data_gprs();
dummy = U1LSR;
break;
default:
break;
}
}
VICVectAddr = 0; /* Acknowledge Interrupt */
}
did you try polling the serial port first against a dumb terminal (hyperterm, minicom, putty) to make sure you have the basics then move on to interrupts?

Resources