DSP

51学习笔记

2019-07-13 19:39发布

#嵌入式工程师所需的技能: 1、工作经验在3年以上,熟练掌握.数字电路和模拟电路设计。熟练使用示波器等常用测试仪器;
2、熟练使用Altium Designer、orCAD、PADS等常用软件,绘制电路原理图及PCB,电路板图Layout;
3、熟练掌握嵌入式设计. 有STM32,AVR ,MSP430 , ARM、DSP、FPGA系列其中2款以上的使用开发经验;
4、熟悉常用的总线及协议,如WIFI、MODBUS、CAN、RS232、RS485、SPI、I2C、1-WIR等常用协议或协议栈.
5、有EMC、EMI等防护设计经验者优先
/*******************************************************************************************/

#在定义指针变量时应为:
int/char/void/float *P=NULL;
防止野指针的出现;

#注意:在C语言中所有变量的声明都必须要放在语句的前面;即放在整个作用域的开头。
C语言的变量不能随用随定义!!!!!!!!!!
gcc在这方面做得不够严谨

#一维数组数组或指针作为函数参数的相似之处:
void fun(int *p) 等价于 void fun(int a[]);

#注意VC与Gcc编译环境的区别!!!

#C语言中的数组调用方法只有一个,那就是地址!!!

#字符串常量就是一个地址:"meng yongzhi" 就是一个代表字符串起始地址的地址常量!!!!

#typedef的使用:typedef
1,    char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,  
             // 和一个字符变量;  
2,   typedef char* PCHAR;  //这样即可;
      PCHAR pa, pb;


#在使用uint和uchar时一定要注意变量的变化范围,一定不可以让其出现负数的情况,否则会出现错误。

#VS1838遥控器原理:发射的编码前16位是身份识别码,能区分不同的电器设备,后16位是8位操作码及其反码。编码的发射方式是从低位到高位。注意输出的高低电平和发射端是反相的,这样的目的是为了提高接收的灵敏度。

#外部中断产生条件配置:TCON寄存器中的ITX中断选择,ITX=1为下降沿触发;ITX=0为低电平触发。

#在51单片机中,未赋初值的变量默认值为0.

#C语言学习:二级指针不能指向二维数组。

#二级指针:指向指针变量的指针!C语言的二维数组在内存中元素是一维线性排列的。

#例子:int a[3][4]
C语言规定数组名a表示数组的首地址,a也就相当于&a[0][0]的值,也就是说a是数组元素a[0][0]的地址。对于&a,指的是整个数组所占的内存空间的首地址,所以&a也等于&a[0][0],所以:a和&a是相同的。

/***********************************************使用指针对二维数组的进行访问******************************************************/
/****二维数组就类似于二级指针,使用方法和二级指针相同,但是二级指针不能指向二维数组!!
/****利用指针使用二维数组的方法只有两种:
一:一级指针法
二:行指针法

/*******************行指针法*************************************/
#使用行指针int (*p)[] 来访问二级指针。
  int a[10][10];
  int (*p)[10];
   p = a;
  printf("%d",*(*(p+i)+j))   /*****a[i][j]==*(p[i]+j)==*(*(p+i)+j)==(*(p+i))[j]==p[i][j] *********/
/******************一级指针法************************************/
#使用一级指针访问二维数组:
  int *p; int a[10][10];
  p=a[0];
  printf("%d",*(p+i*10+j));
/*********************************************************/



#C语言二维数组的初始化:
1,二维数组在初始化的时候可以省略一维长度:int[][3]={1,2,3,4,5,6};
/****二位数组初始化是必须声明以为长度的原因,二位数组的访问机制:
设有数组:      int a[m][n];
a[i][j]的地址: &a[i][j]=&a[0][0] + i*sizeof(int)*n + j*sizeof(int)

//  一维数组在初始化的时指定所有元素的时候可以省略长度;
//  二维数组在初始化的时候可以省略一维长度;
//  在函数形参表中,允许不给出形参数组的长度,或用一个变量来表示数组元素的个数。例如,可以写为:
    void nzp(int a[])   
//void Func(int array[ ][10]);因为数组的行数无关紧要,所以二维数组作为函数形参的时候可以省略以为长度。
/*********************************************************/
#switch的使用
    scanf("%d",&a);
    switch (a){
        case 1:printf("Monday ");  break;
        case 2:printf("Tuesday ");   break;
        case 3:printf("Wednesday ");  break;
        case 4:printf("Thursday ");  break;
        case 5:printf("Friday ");  break;
        case 6:printf("Saturday ");  break;
        case 7:printf("Sunday ");  break;
        default:printf("error ");
    }
/**********************************************************/
#指向函数的指针:
1,定义:void/int/float (*P)(int,int);
       函数的返回值类型 /指针变量名/形参表
2,初始化:P=函数名;
3,调用:  (*P)(x,y);   //调用时只需要将函数名用(*P)名代替函数名就可以了,后面的实参照旧;

/*****************指向函数的指针的主要作用******************************************/
#函数指针作为函数的形数:(在多个不确定的类似的函数中任选一个作为某个函数的参数)
教材实例:
    #include

    void MyFun1(int x);
    void MyFun2(int x);
    void MyFun3(int x);
    typedef void (*FunType)(int ); /* ②. 定义一个函数指针类型FunType,与①函数类型一致 */
    void CallMyFun(FunType fp,int x);

    int main(int argc, char* argv[])
    {

        CallMyFun(MyFun1,10); /* ⑤. 通过 CallMyFun 函数分别调用三个不同的函数 */
        CallMyFun(MyFun2,20);
        CallMyFun(MyFun3,30);
        return 0;
    }

    void CallMyFun(FunType fp,int x) /* ③. 参数fp的类型是 FunType。*/
    {
        fp(x);/* ④ . 通过fp的指针执行传递进来的函数,注意fp所指的函数是有一个参数的。 */

    }

    void MyFun1(int x) /* ①. 这是个有一个参数的函数,以下两个函数也相同。 */
    {

        printf("函数MyFun1 中输出:%d ",x);

    }

    void MyFun2(int x)
    {

        printf("函数MyFun2 中输出:%d ",x);

    }
    void MyFun3(int x)
    {

        printf("函数MyFun3 中输出:%d ",x);

    }
/***********************************************************/
#返回指针的函数:
又是后需要让函数返回一个地址,这事就需要用到返回指针的函数了
定义:int *fun(int x,int y)
         {
        函数体;
     }
//字符串数组
#作用:当数组元素是字符串的时候,返回字符串的首地址并输出;
例:char *fun(int n)
{
    char *name[]={"MENG","YONG","ZHI"}
    return name[n];
}
/***********************************************************/



/***********************数组元素作为函数的参数**********************************/
1,数组元素直接作为函数的参数:
int fun(int n)
   {  函数体;  }
fun(a[1]);  二位数组也类似



/*************************数组作为函数的参数**********************************************/
##一维数组作为函数参数:首先抛结论:
1:C语言中,当一维数组做函数参数时,编译器总是把它解析成一个指向其首元素的指针。
2:实际传递的数组大小与函数形参指定的数组大小没有关系。
#一维数组作为函数实参的两种使用方法:
1:void fun(int a[])编译器把array解析成指向整形元素的指针,也就是数组的首地址,方括号中加不加指定数字都可以,因为编译器根本不看,因此                    最好不写,以免引起误解。

2: void fun(int* p) 直接使用指针的方法。

##二维数组作为函数的参数: int a[3][3]
1,一级指针法:
  int fun(int *p){  函数体;  }
   fun(a[0]);
2:行指针法:
   int fun(int (*p)[3]) {  函数体;  }  //列数一定要写;
   fun(a);
3:基本法:
   int a[m][n];
   int fun(a[m][n]){  函数体;  }
   fun(a);

/**********************************字符串*****************************************************/
字符串的初始化方法:
1,char a[]="meng yongzhi";
2,char *p="meng yongzhi";   /***这两种方法的区别是储存方式的不同
#如果要改变a[]代表的数组的内容,就要改变数组元素的内容。其在内存中占据了一个数组的长度;
#如果要改变P所指向的数组,只要将P指向一个新的地址。P在内存中占据着一个可以存放内存地址的内存单元;
#
//注意字符串的输出:printf("%s",str);//str是一个地址
/********改变字符串的值的方法:
1,strcpy(a,"meng");  //数组字符串不能直接改变其值,只有这一种方法!!!
2,p="meng";            //分别改变了a和p的值;a="meng"是非法的,因为a是指针常量,不能对它进行赋值;

/*****指针数组******/
C语言中的数组元素类型可以为任意类型,如果数组元素为指针类型,用于存放地址,那么这个数组就是指针数组;
指针数组的主要用途就是对多个字符串进行处理操作,因此在实际操作中,字符指针数组更为常见。(字符指针数组和二维数组又是能够解决同样的问题,但在字符串操作中,字符指针数组更为有效)