MY friend is trying to program a shift register ic 74hc595 with 8051 microcontroller attached to display a moving led message.
But my compiler is giving me error in send_data(alf(a));
Here is code->
#include<8051.h>
#define clock P2_0
#define data_bit P2_1
#define latch P2_2
#define shift 8
void delay(unsigned int i)
{
int k=0;
while(k<i)
{
k++;
}
}
void send_data(unsigned char temp)
{
unsigned char i;
unsigned char dd;
latch=0;
clock=0;
for(i=0;i<shift;i++){
dd=temp>>i;
if(dd&1)
data_bit=1;
else
data_bit=0;
clock=1;
clock=0;
}
latch=1;
}
unsigned char alf[]={16,6,6,16};
void main()
{
unsigned char a;
while(1){
for(a=0;a<4;a++)
{
send_data(alf(a));
delay(10000);
}
}
}
Since its my friend who is making, i dont have much info about it. But if anything else is needed, please tell and i will provide but please help me solve this prob.
Thanks.
send_data(alf(a));
should be
send_data(alf[a]);
On the other hand, the body of delay can be optimized (and removed) by your compiler, take a look to the volatile keyword
In your case alf is an array not a function. If alf is a function then you can call alf(a). For array you need to pass index so you need to call alf[a].
Related
On this circuit and code, I tried to make a counter that when no one pass through (for example it is a passage at the metro station), there will read 1 value at RC7 lead of the processor. If someone pass through the signal change to 0. And program will count the how many people pass away over there and show the number of people on the 7-Segment LCD until 10. When 10 people pass through of the passage, the LED (D1) will be blinking for 1 seconds.
I tried to write a code about this algorithm, and when I load it to Pic18F45K22 but, it is not working. Proteus show error message like,
[PIC18] PC=0x0000. $MCLR$ is low. Processor is in reset. [U1]
The circuit that I designed given at below Figure 1:
The solutions that I tried:
I used pull-up resistors. It did not work.
We describe the frequency value in Micro C code. It did not work.
And the algorithm given at below:
#include <xc.h>
#define _XTAL_FREQ 4000000
unsigned char x=0;
void MSDelay(unsigned int);
void main()
{
TRISC=0xff;
TRISA=0x00;
while(1)
{
if (PORTC==0)
{
x++;
MSDelay(200);
}
if (x==1)
{
PORTA==0x3f;
}
if (x==2)
{
PORTA==0x06;
}
if (x==3)
{
PORTA==0x5b;
}
if (x==4)
{
PORTA==0x4f;
}
if (x==5)
{
PORTA==0x66;
}
if (x==6)
{
PORTA==0x6d;
}
}
}
void MSDelay(unsigned int itime){ //for delay
unsigned int i;
unsigned int j;
for(i=0;i<itime;i++){
for(j=0;j<165;j++){
}
}
}
So I make the answer for you:
The error ist here:
if (x==1)
{
PORTA==0x3f;
}
If you want assign a value you need = and not ==
if (x==1)
{
PORTA=0x3f;
}
Working in embedded Systems design, I am often confronted with Legacy Code, where somebody wrote some ISR which consists of a huge if/else-Jungle, sometimes spanning multiple screen-lengths. Now, trying to be a good programmer I try to refactor the function, using the paradigms I learned, one of them being: "A function should do one thing only".
So I break down the function into multiple static sub-function, which have descriptive names and encapsulate variables. But since I am working on an embedded device, I need to be considerate of stacksize and the number of jumps (especially in an ISR that might get called often and might itself get interrupted by something else).
Now, of cause most(or even all) Compilers can be forced to inline a function (as __always_inline does with gcc). But even that increases stacksize, if I have to pass parameters (they do not necessarily get optimized away), even if it is just a few bytes per parameter.
Now for my actual question: Is there a way not to increase stacksize while breaking up functions in C?
EDIT:
To make my Question clearer: Here is an Example of some Code, where I just shifted some of the code to inline-functions.
Static stack usage is 144 without inline-functions and 160 with inline functions.
Original:
#include <stdio.h>
#include <string.h>
int main(){
char inputString[100];
scanf("%s",inputString);
static char delimiterArray[] = {' ','+','-','/','*','='};
for(int i = 0; i<sizeof(inputString); i++){
printf("%c",inputString[i]);
char* inputChar = inputString + i;
for(int j = 0; j<sizeof(delimiterArray);j++){
if( *inputChar == delimiterArray[j]){
printf("DELIMITER: %c",delimiterArray[j]);
}
if(inputString[i] == '\0'){
printf("\nNuberOfChars: %d\n",i);
break;
}
}
}
return 0;
}
With inline-functions:
#include <stdio.h>
#include <string.h>
static inline void checkForDelimiters(char* inputChar)__attribute__((always_inline));
static inline void decomposeString(char* inputString)__attribute__((always_inline));
int main(){
char inputString[100];
scanf("%s",inputString);
decomposeString(inputString);
return 0;
}
static void checkForDelimiters(char* inputChar){
static char delimiterArray[] = {' ','+','-','/','*','='};
for(int j = 0; j<sizeof(delimiterArray);j++){
if(*inputChar == delimiterArray[j]){
printf("DELIMITER: %c",delimiterArray[j]);
}
}
}
static void decomposeString(char* inputString){
for(int i = 0; i<sizeof(inputString); i++){
printf("%c",inputString[i]);
checkForDelimiters(inputString+i);
if(inputString[i] == '\0'){
printf("\nNuberOfChars: %d\n",i);
break;
}
}
}
I am trying to run this program. It uses the interrupts and when we press w, it replace it by s in keyboard buffer
#include "stdafx.h"
#include "stdio.h"
#include "bios.h"
#include <dos.h>
void interrupt_oldint15(*oldint15);
void interrupt_newint15(unsigned int BP, unsigned int DI, unsigned int SI, unsigned int DS,
unsigned int ES, unsigned int DX, unsigned int CX, unsigned int BX,
unsigned int AX, unsigned int IP, unsigned int CS, unsigned int flags);
void main ( )
{
oldint15 = getvect (0x15);
setvect (0x15, newint15);
keep (0, 1000);
}
void interrupt_newint15 (unsigned int BP, unsigned int DI, unsigned int SI, unsigned int DS, unsigned int ES, unsigned int DX, unsigned int CX, unsigned int BX, unsigned int AX, unsigned int IP, unsigned int CS, unsigned int flags )
{
if(*((char*)&AX)==0x11)
*((char*)&AX)=0x1F;
else if(*((char*)&AX)==0x1F)
*((char*)&AX)=0x11;
}
but it gives the error in getvect and setvect functions.
for one thing, interrupt functions, in C, do not have parameters, nor a returned value.
Listing all the registers is a waste of space (besides which it should not compile) as the entry into a interrupt event causes a saving of all the key registers (typically on the stack of the currently running process)
All the key registers (like the PC and Status registers) are restored upon exit from the interrupt.
The compiler will cause any general purpose registers changed in the interrupt function to be saved/restored.) If you are working at such a low level, then you should know exactly where the interrupt vectors are located, you should have a code segment that overlays the interrupt vectors and another code segment that mirrors the interrupt vectors.
Then, you copy the current set of interrupt vectors to the mirror and then replace the desired individual vector with a pointer to the interrupt function you wrote. At the end of your code, you need to copy the vector back into the original vector area.
It could be that functions you are having trouble with do those operations for you.
this, from a very old post, from a c.comp news group may be helpful:
You are mixing languages. In Borland C an "interrupt" has type
void (interrupt*)()
while in Borland C++ it has type
void (interrupt*)(...)
This affects the parameter type of setvect and the return type of
getvect which change in the same way according to the language used.
You obviously compiled your program as a C++ program and not as a C
program because according to the compiler's message 'oldvec' is
declared as a "C interrupt" and getvect returns a "C++ interrupt".
the format for using get/set vect() in C, which look nothing like your C++ example is:
tick_isr_old = getvect(0x08);
setvect(0x08, (void interrupt (*)(void)) tick_isr);
As mentioned already, the functions getvect() and setvect() are only available with Borland/Turbo C++. The functions _dos_getvect() and _dos_setvect() are almost identical and offer better portability across compilers (Borland/Turbo C++, MS Visual C++ 1.x, Open Watcom C++). They should be defined in <dos.h>.
Here is an example of their use (prints an '#' every second):
/*** Includes ***/
#include <stdint.h> // int*_t, uint*_t
#include <stdbool.h> // bool, true, false
#include <dos.h> // _chain_intr(), _dos_getvect() , _dos_setvect()
#include <stdio.h> // putchar()
/*** Definitions ***/
#define TICKS_PER_SEC 18ul
#define VECT_TIMER 0x1C
/*** Global Variables ***/
bool timer_hooked = false;
bool timer_1sec_elapsed = false;
uint32_t ticks = 0;
void (interrupt far * OrigTimerH)( ); // vector to original 0x1C handler
/*** Functions ***/
static void interrupt far TimerH( void ) {
ticks++;
if ( ticks % TICKS_PER_SEC == 0 ) {
timer_1sec_elapsed = true;
}
_chain_intr( OrigTimerH ); // handler callback
}
void TimerStart( void ) {
__asm { cli } // critical section; halt interrupts
OrigTimerH = _dos_getvect( VECT_TIMER ); // save original vector
_dos_setvect( VECT_TIMER, TimerH ); // put our handler in the vector
timer_hooked = true; // remember that we're hooked if we wanted to unhook
__asm { sti } // resume interrupts
}
int main( void ) {
TimerStart();
while ( true ) {
if ( timer_1sec_elapsed ) {
timer_1sec_elapsed = false;
putchar('#');
}
}
}
I have a problem I need to solve and I have no freaking idea how to do it. If someone would be willing to help I would very much appreciate it. I know I'm asking for a lot, but I really need it.
Create a program for interpretation of a simple instruction set consisting of the instructions: MVI, MOV, AND, OR, NOT, LESS, LEQ, GRE, GEQ, JMP, PRN, SUM, SUB, PRB, SL and SR, described in this document. Your task is to make a program that takes as an input a binary representation of a list of instructions, and as an output it prints the corresponding result (after the execution of the instructions). The input can contain all the instructions except SUB and PRB that you do not have to implement. Conversion from binary system to any other numeral system should not be made, except at the moment when you need to find the line that should be executed next when the condition is satisfied (GRE, GEQ, LESS, LEQ, JMP), but the comparison of the numbers in the condition should be made based on the binary representatio/pn. All data are represented in SM binary system. There are eight 16-bit registers available enumerated from 0 to 7.
#include<stdio.h>
#define MAX 1000
char registers[8][16];
void MVI(int reg, char *value) {
// code here
}
void MOV(int reg1, int reg2) {
// code here
}
void AND(int reg1, int reg2, int reg3) {
// code here
}
void OR(int reg1, int reg2, int reg3) {
// code here
}
void NOT(int reg1, int reg2) {
// code here
}
void PRN(int reg) {
// code here
}
void SUM(int reg1, int reg2, int reg3) {
// code here
}
void SL(int reg) {
// code here
}
void SR(int reg) {
// code here
}
int main() {
int i,j,k;
int N = 0; // number of lines in the input
char c;
char lines[MAX][16];
while (1) {
scanf("%c", &c);
if (c == '\n') {
break;
}
lines[N][0] = c;
for (i=1;i<16;i++) {
scanf("%c", &lines[N][i]);
}
N++;
scanf("%c", &c);
}
for (i = 0; i < 8; i++) {
for (j = 0; j < 16; j++) {
registers[i][j] = '0';
}
}
// code here
return 0;
}
I think the big piece you need is dispatching the functions based on the source line. There are a number of ways you can do this, but a useful piece for all of them is strstr(a,b)==a which will check if the string a begins with the contents of the string b.
You can do a chain of if-else blocks.
if (strstr(line[i], "SUM")==line[i]){
SUM(...);
} else if (strstr(line[i], "AND")==line[i]) {
AND(...);
}
Or you can precompile the user program by scanning for the opcodes when you read the source and store them as single-byte small codes. You would want the uppercase identifiers to be enum values, and use the lowercase versions for the function names. Then the chain is simpler.
if (line[i][0] == SUM) {
SUM(...);
} else if (line[i][0] == AND) {
AND(...);
}
But, with small integer codes, there are even better ways. A switch.
switch(line[i][0]){
case SUM: sum(...); break;
case AND: and(...); break;
}
A function table. But this is where you have be clever. A function must always be called with arguments of the correct type, but function-pointers allow you to bypass the compiler's ability
to check that this is so. So for this method, all functions should have the same arguments since
they are all called by a single function-call line.
void (*optab[])(...) = { sum, and, ... };
optab[ line[i][0] ](...); // calls sum() or and() by using the opcode in the array lookup
I want to see how much is taken by the C program, so I wrote:
#include<stdio.h>
#include<stdlib.h>
#include"memory.h"
#include"memory_debug.h"
#include<sys/times.h>
#include<unistd.h>
int (*deallocate_ptr)(memContainer *,void*);
void (*merge_ptr)(node *);
void* (*allocate_ptr)(memContainer *,unsigned long size);
memContainer* (*init_ptr)(unsigned long );
diagStruct* (*diagnose_ptr)(memContainer *);
void (*finalize_ptr)(memContainer *);
void (*printNode_ptr)(node *n);
void (*printContainer_ptr)(memContainer *c);
void info(memContainer *c)
{
struct tms *t;
t=malloc(sizeof(struct tms));
times(t);
printf("user : %d\nsystem : %d\n %d",t->tms_utime,(int)t->tms_stime);
diagnose_ptr(c);
printf("\n");
return ;
}
but when I invoke this function I get 0 user time and 0 system time, even if I write:
for (i=0;i<100000;++i)
for (j=0;j<10;++j)
{}
info(c);
what am I doing wrong?
The compiler probably optimizes away your for loops since they do nothing. Try incrementing a volatile variable.
If you only want to know the time, try running time ./app and it will print the cputime, wall clock time etc of the executed app.
The code could simply write a volatile variable at the start, put your 'work' in a function (in a separate file), then read the volatile after the 'work' and print something involving the volatile.
Or do some simple calculation with a part of the calculation buried in a function, or using a function return.
What platform (Operating system & Compiler) are you using?
I don't know what platform you are running on, but there are a few useful questions on stackoverflow about higher precision system clocks. High precision timing in userspace in Linux has several useful links and references.
Timing Methods in C++ Under Linux looked useful.
The below demo program outputs nonzero times:
#include<stdio.h>
#include<stdlib.h>
#include"memory.h"
#include<sys/times.h>
#include<unistd.h>
#include <iostream>
using namespace std;
int main()
{
int x = 0;
for (int i = 0; i < 1 << 30; i++)
x++;
struct tms t;
times(&t);
cout << t.tms_utime << endl;
cout << t.tms_stime << endl;
return x;
}
Output:
275
1