Project#1:
In this project, you are going to design and develop a simple embedded Application to exploring interfacing through input/output ports. This project has two parts described as below:
Hardware:
In this project, you will be using the Explorer 16 development board. Specifically, you will be using the 8 LEDs on the board to generate a Knight Rider Pattern on those LEDs. Please, check Explorer16.pdf for pin connections.
Part A:
Write an application (in C) which implement the sequence as below:
1. Make all the LEDs OFF.
2. Make LED D3 (Right most) to be ON .
3. After a while (a delay of your choice), make next (to the Left) LED to be ON.
4. After a while, make the next LED to be ON. Repeat this process until all the 8 LEDs (from Right most to LEFT most) becomes ON.
5. Repeat the above processes (1-4), this time, starting from LEFT most LED and walk to the RIGHT most.
6. Repeat the above sequence (1-5) infinitely.
Part B:
Utilize SW3 of the explorer 16 board to change the direction of the Knight Rider Pattern designed in Part A. Any time, if SW3 is pushed down and hold, the above pattern starts from LEFT to RIGHT and when SW3 is released, the pattern walks from RIGHT to LEFT (as in Part A).
Make two seperate codes for Part A and Part B.
15 answers
```c
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#pragma config WDT = OFF
#define _XTAL_FREQ 8000000
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i=0; i<8; i++) {
LATA = (1 << i);
__delay_ms(200); // Delay between LEDs turning on
}
// Left to Right sequence
for(int i=6; i>=0; i--) {
LATA = (1 << i);
__delay_ms(200); // Delay between LEDs turning on
}
}
return;
}
```
And here is an example code for Part B:
```c
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#pragma config WDT = OFF
#define _XTAL_FREQ 8000000
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i=0; i<8; i++) {
LATA = (1 << i);
__delay_ms(200); // Delay between LEDs turning on
}
// Left to Right sequence if SW3 is pressed
if(PORTDbits.RD7 == 0) {
for(int i=6; i>=0; i--) {
LATA = (1 << i);
__delay_ms(200); // Delay between LEDs turning on
}
}
}
return;
}
```
```c
#include <xc.h>
#include <stdint.h>
#pragma config WDT = OFF
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i=0; i<8; i++) {
LATA = (1 << i);
__delay_ms(200); // Delay between LEDs turning on
}
// Left to Right sequence
for(int i=6; i>=0; i--) {
LATA = (1 << i);
__delay_ms(200); // Delay between LEDs turning on
}
}
return;
}
```
This simplified code does not include unnecessary header files and variables, making it easier to understand and follow.
```c
#include <xc.h>
#pragma config WDT = OFF
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i=0; i<8; i++) {
LATA = (1 << i);
__delay_ms(200); // Delay between LEDs turning on
}
// Left to Right sequence if SW3 is pressed
if(PORTDbits.RD7 == 0) {
for(int i=6; i>=0; i--) {
LATA = (1 << i);
__delay_ms(200); // Delay between LEDs turning on
}
}
}
return;
}
```
This simplified code does not include unnecessary header files and comments, making it easier to understand and follow.
```c
#include <xc.h>
#pragma config WDT = OFF
void delay_ms(unsigned int milliseconds) {
for(unsigned int i=0; i<milliseconds; i++) {
__delay_ms(1);
}
}
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i=0; i<8; i++) {
LATA = (1 << i);
delay_ms(200); // Delay between LEDs turning on
}
// Left to Right sequence if SW3 is pressed
if(PORTDbits.RD7 == 0) {
for(int i=6; i>=0; i--) {
LATA = (1 << i);
delay_ms(200); // Delay between LEDs turning on
}
}
}
return;
}
```
In this example, a new function `delay_ms()` is defined, which takes the desired delay time in milliseconds as an argument. The function uses a simple loop to call `__delay_ms(1)` for the specified number of milliseconds. This allows the main program to call `delay_ms()` and provide a delay value directly without needing to modify the `__delay_ms()` function itself.
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i=0; i<8; i++) {
LATA = (1 << i);
delayFunc();
}
// Left to Right sequence
for(int i=6; i>=0; i--) {
LATA = (1 << i);
delayFunc();
}
}
return;
}
void delayFunc(void)
{
for(i = 0; i <100; i++)
{
for(j=0; j < 20; j++)
{
k=j;
}
}
}
1. You need to declare the variables `i`, `j`, and `k` in the `delayFunc()` function. Add the following line at the beginning of the `delayFunc()` function:
```c
int i, j, k;
```
2. In the outer loop of the `delayFunc()` function, the condition `i < 100` should be changed to `i < 1000` to achieve a longer delay.
```c
for(i = 0; i < 1000; i++)
```
Here's the corrected code for Part A:
```c
#include <xc.h>
#pragma config WDT = OFF
void delayFunc(void)
{
int i, j, k;
for(i = 0; i < 1000; i++)
{
for(j=0; j < 20; j++)
{
k = j;
}
}
}
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i=0; i<8; i++) {
LATA = (1 << i);
delayFunc();
}
// Left to Right sequence
for(int i=6; i>=0; i--) {
LATA = (1 << i);
delayFunc();
}
}
return;
}
```
This modified code should work correctly and generate the desired Knight Rider pattern. Note that the `delayFunc()` function provides a delay by looping for a certain number of iterations. Adjust the loops and counts as needed to achieve the desired delay duration.
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i=0; i<8; i++) {
LATA = (1 << i);
delayFunc();
}
// Left to Right sequence if SW3 is pressed
if(PORTDbits.RD7 == 0) {
for(int i=6; i>=0; i--) {
LATA = (1 << i);
delayFunc();
}
}
}
return;
}
void delayFunc(void){
int i, j, k;
for(i = 0; i < 1000; i++){
for(j=0; j < 20; j++){
k = j;
}
}
}
In the condition `if(PORTDbits.RD7 == 0)`, make sure to check the state of SW3 by comparing it to `1`, not `0`. Since SW3 is active-low (pressed when the corresponding pin is logic low), the condition should be `if(PORTDbits.RD7 == 1)`.
Here's the corrected code for Part B:
```c
#include <xc.h>
#pragma config WDT = OFF
void delayFunc(void){
int i, j, k;
for(i = 0; i < 1000; i++){
for(j=0; j < 20; j++){
k = j;
}
}
}
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i=0; i<8; i++) {
LATA = (1 << i);
delayFunc();
}
// Left to Right sequence if SW3 is pressed
if(PORTDbits.RD7 == 1) {
for(int i=6; i>=0; i--) {
LATA = (1 << i);
delayFunc();
}
}
}
return;
}
```
This modified code should work correctly, generating the Knight Rider pattern that changes direction based on the state of SW3. Remember to adjust the timing in the `delayFunc()` function as needed to achieve the desired delay duration.
```c
#include <xc.h>
#pragma config WDT = OFF
void delayFunc(void) {
for(int i = 0; i < 1000; i++) {
for(int j = 0; j < 20; j++) {
asm("NOP");
}
}
}
void main(void) {
TRISA = 0x00;
LATA = 0x00;
int direction = 0; // 0: Right to Left, 1: Left to Right
while(1) {
// Right to Left sequence
if(direction == 0) {
for(int i = 0; i < 8; i++) {
LATA = (1 << i);
delayFunc();
}
direction = 1;
}
// Left to Right sequence if SW3 is pressed
if(PORTDbits.RD7 == 0) {
direction = 0;
}
// Left to Right sequence
if(direction == 1) {
for(int i = 6; i >= 0; i--) {
LATA = (1 << i);
delayFunc();
}
}
// Right to Left sequence if SW3 is pressed
if(PORTDbits.RD7 == 0) {
direction = 1;
}
}
return;
}
```
In this updated code, a new variable `direction` is introduced to keep track of the current direction of the Knight Rider pattern. The variable is initially set to 0 (Right to Left). If the SW3 button is pressed, the direction is changed accordingly. Now, the pattern starts from Right to Left, and if SW3 is pressed, the direction changes to Left to Right. Note that the `delayFunc()` function uses an inner `NOP` (No operation) assembly instruction for the delay, providing a more accurate and consistent timing than the previous version.
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i=0; i<8; i++) {
LATA = (1 << i);
delayFunc();
}
// Left to Right sequence
for(int i=6; i>=0; i--) {
LATA = (1 << i);
delayFunc();
}
}
return;
}
void delayFunc(void)
{
for(i = 0; i <100; i++)
{
for(j=0; j < 20; j++)
{
k=j;
}
}
}
Here is the corrected code:
```c
void delayFunc(void)
{
int i, j, k;
for(i = 0; i < 100; i++)
{
for(j = 0; j < 20; j++)
{
k = j;
}
}
}
void main(void) {
TRISA = 0x00;
LATA = 0x00;
while(1) {
// Right to Left sequence
for(int i = 0; i < 8; i++) {
LATA = (1 << i);
delayFunc();
}
// Left to Right sequence
for(int i = 6; i >= 0; i--) {
LATA = (1 << i);
delayFunc();
}
}
return;
}
```
In this corrected code, the variables `i`, `j`, and `k` are declared within the `delayFunc()` function, allowing the function to compile without errors. The rest of the code remains the same.