收藏 分销(赏)

CT107D编程基础手册.doc

上传人:丰**** 文档编号:2954063 上传时间:2024-06-12 格式:DOC 页数:29 大小:93.54KB 下载积分:10 金币
下载 相关 举报
CT107D编程基础手册.doc_第1页
第1页 / 共29页
CT107D编程基础手册.doc_第2页
第2页 / 共29页


点击查看更多>>
资源描述
一、IO口编程 IO编程,该开发板使用了573锁存器,通过P2口5,6,7位连接3-8译码器,扩展出了8个口,其中4个口分别连接4个573锁存器,这里以LED锁存器来举例: 原理图573: 分析代码: P2=((P2&0x1f)|0x80); 其中0x1f=0001 1111,P2与0x1f进行与运算,高三位清零,别的位保持本来状态,不变化,即把控制3-8译码器高三位留出来: 接着再或上0x80;容易发现0x80=1000 0000;或运算,与1或成果为1,与0或成果不变,因此或上0x80只需看P2高三位,则高三位为100,相应3-8译码器话,P2^7=1;P2^6=0;P2^5=0; 因此输出Y4=0;Y4再通过与非运算,看下图示: 则输出Y4C=1;即LED相应锁存器片选信号被选中,锁存器打通,接下来就可以对P0口进行操作,操作完之后, P2=P2&0x1f;P2高三位直接清零,此时Y4C=0,则把锁存器锁上了。 类似办法,数码管、蜂鸣器等都是如此操作, 选中锁存器代码: P2=((P2&0x1f)|(这里填相应锁存器位移号))。 二、              数码管动态扫描和定期器 数码管显示分为段选和位选, 数码管定义和显示函数: Code unsigned char tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; unsigned chardspbuf[]={10,10,10,10,10,10,10,10}; unsigned chardspcom=0; void display() { //段选,消隐 P2=((P2&0x1f)|0xe0); P0=0xff; P2=P2&0x1f; //位选 P2=((P2&0x1f)|0xc0); P0=(1<<dspcom); P2=P2&0x1f; //段码输入 P2=((P2&0x1f)|0xe0); P0=tab[dspbuf[dspcom]]; P2=P2&0x1f; if(++dspcom==8)        dspcom=0; } 注意:这里1左移dspcom位,刚开始dspcom=0,则1左移dspcom位仍旧为1,接着dspcom每次自增1,1相应二进制00000001,即把1每次向左移,每次都比上一次多移一位,直至8位移完,相应8个数码管。 定期器配备: 这里只需记住定期器配备,懂得怎么使用就可以了。一方面有两个定期器,T0和T1,(也有单片机有T2),定期器有4种工作方式0,1,2,3;其中最惯用是方式1(16位),另一方面是方式2(8位自动重装,串口通讯中断会用到)。 定期器需要配备:TMOD |=0x01;配备成使用定期器0,工作方式为1;同理使用定期器1工作方式1:TMOD|=0x10;则同步使用两个定期器且工作方式为1,那么可以:TMOD|=0x11; 定期器1配备成工作方式2:TMOD |=0x20; 接着配备(以定期器0举例): TH0=(65535-)/256;//配备初值 TL0=(65535-)%6; ET0=1; TR0=1;//定期0中断 EA=1;//总中断 定期器1也是同理,只但是0要改成1. 接着定期中断函数和优先级: 定期器0 void isr_timer_0(void) interrupt1  //默认中断优先级1 {     TH0= (65536-)/256;     TL0= (65536-)%6;  //定期器重载    display(); } 定期器1: voidisr_timer_1(void)  interrupt 3 //默认中断优先级3 {     TH0= (65536-)/256;     TL0= (65536-)%6;  //定期器重载    display(); } 注意:定期器0优先级为1,定期器1为3,串口中断优先级为4,总共有5个中断源,背面还会简介外部中断和串口中断。 数码管动态扫描,显示函数放在定期中断函数里面,2ms扫一次是最稳定!! 三、              矩阵键盘 矩阵键盘需要死记了!这里不再讲独立键盘。 第二种单片机键盘扫描代码(没有消抖): sfrP4^4=0xC0; //键盘定义 sbitr1=P3^0;  //4行 sbit r2=P3^1; sbit r3=P3^2; sbit r4=P3^3; //4列 sbit c1=P4^4; sbit c2=P4^2; sbit c3=P3^5; sbit c4=P3^4; //读取矩阵键盘键值 unsigned charkey_scan() {     unsigned char key_value;     r1=0;     r2=r3=r4=1;     c1=c2=c3=c4=1;     if(!c1) key_value=0;     else if(!c2) key_value=1;     else if(!c3) key_value=2;     else if(!c4) key_value=3;    r2=0;     r1=r3=r4=1;     c1=c2=c3=c4=1;     if(!c1) key_value=4;     else if(!c2) key_value=5;     else if(!c3) key_value=6;     else if(!c4) key_value=7;     r3=0;     r2=r1=r4=1;     c1=c2=c3=c4=1;     if(!c1) key_value=8;     else if(!c2) key_value=9;     else if(!c3) key_value=10;     else if(!c4) key_value=11;     r4=0;     r2=r3=r1=1;     c1=c2=c3=c4=1;     if(!c1) key_value=12;     else if(!c2) key_value=13;     else if(!c3) key_value=14;     else if(!c4) key_value=15;     return key_value; } 四、              串口通讯和串口中断 串口中断配备只需记住几种寄存器就行了, 初始化:   SCON =0x50;//串口配备成模式1 TMOD|=0x20;//定期器1,方式2,8位自动重装 TH1=256-(unsigbedchar)(SYSTEMCLOK/BAUDRATE/384+0.5);//定期初值         ES=1;        //串口中断打开         TR1=1;     //启动定期器1         EA=1;           //总中断打开 这里必要使用定期器1,不能用定期器0. 下面是模块化函数: void Uart_Init() { SCON = 0x50; TMOD |=0x20; TH1=256-(SYSREMCLOCK/BAUDRATE/384+0.5); ES=1; TR1=1; EA=1; } void UartSend(unsignedchar*pBuff,int length) { unsigned charc; int i=0; for(i=0;i { c=pBuff; SBUF=c; while(TI==0); TI=0; } } 接受数据可以这样写: 定义全局变量: unsigned charuart_buf[100];//串口缓冲区 unsignedint  uart_Count=0;//串口数据长度 void uart_inte()interrupt 4 {      unsigned char c;      if(RI)      {             RI=0;             c=SBUF;             uart_buf[uart_Count]=c;             uart_Count++;      }                           } 如果可以指定接受,可以这样写 //串口中断服务函数 void isr_uart(void)interrupt 4{    if(RI){        RI = 0;  //清除接受标志位        rxbuf[rxcnt] = SBUF;        if(rxbuf[rxcnt] == '\n'){            rxcnt = 0;            rx_over = 1;            ES = 0; //回车为接受结束标志,检测到回车符后,关闭串口中断        }                  else{                    rxcnt++;             }    } } 当接受完一帧数据时关闭串口中断,设一种标志位,解决完之后再打开。 #include"reg51.h" #include"intrins.h" typedef unsigned charBYTE; typedef unsigned intWORD; BYTEcode_tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; char arry[10]="I CANPLAY"; unsigned charx; #define FOSC11059200//1000L         //系统频率 #define BAUD115200            //串口波特率 #defineNONE_PARITY    0      //无校验 #defineODD_PARITY     1      //奇校验 #defineEVEN_PARITY    2      //偶校验 #defineMARK_PARITY    3      //标记校验 #defineSPACE_PARITY   4      //空白校验 #define PARITYBITNONE_PARITY  //定义校验位 sfrAUXR  =0x8e;              //辅助寄存器 sfrP_SW1   =0xA2;            //外设功能切换寄存器1 #define S1_S00x40             //P_SW1.6 #define S1_S10x80             //P_SW1.7 sbit P22 =P2^2; bit busy; void SendData(BYTEdat); void SendString(char*s); void main() {     ACC= P_SW1;     ACC&= ~(S1_S0 |S1_S1);   //S1_S0=0 S1_S1=0    P_SW1 =ACC;               //(P3.0/RxD,P3.1/TxD)     //  ACC= P_SW1; //  ACC&= ~(S1_S0 |S1_S1);   //S1_S0=1 S1_S1=0 //  ACC|=S1_S0;              //(P3.6/RxD_2,P3.7/TxD_2) // P_SW1 = ACC; // //  ACC= P_SW1; //  ACC&= ~(S1_S0 |S1_S1);   //S1_S0=0 S1_S1=1 //  ACC|=S1_S1;              //(P1.6/RxD_3,P1.7/TxD_3) // P_SW1 = ACC; //#if (PARITYBIT ==NONE_PARITY)     SCON=0x50;               //8位可变波特率 //#elif (PARITYBIT ==ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT ==MARK_PARITY) //  SCON =0xda;               //9位可变波特率,校验位初始为1 //#elif (PARITYBIT ==SPACE_PARITY) //  SCON =0xd2;               //9位可变波特率,校验位初始为0 //#endif     AUXR=0x40;               //定期器1为1T模式     TMOD=0x20;               //定期器1为模式2(8位自动重载)     TL1= (256 - (FOSC/32/BAUD));  //设立波特率重装值     TH1= (256 - (FOSC/32/BAUD));     TR1=1;                   //定期器1开始工作     ES =1;                    //使能串口中断     EA =1;    while(1)      { //  SendString(arry);      SendString("I CAN PLAY~~\r\n");//上位机显示接受文本模式 //  SendData(x);      } } void Uart() interrupt 4using 1 {     if(RI)//单片机接受数据,发送数字0~9,可在数码管上显示,发送hex模式    {        RI =0;                //清除RI位 //       P0= SBUF;             x=SBUF;//将缓存器数据赋值给x             P0=0xff;               //消隐             P2|=0xe0;             P2&=0x1f;                          P0=code_tab[x];               //段选             P2|=0xe0;             P2&=0x1f;                          P0=0x01;                          //位选第一位             P2|=0xc0;             P2&=0x3f;        }     if(TI)    {        TI =0;                //清除TI位        busy =0;              //清忙标志    } } void SendData(BYTEdat) {    while(busy);              //等待前面数据发送完毕     ACC=dat;                 //获取校验位P (PSW.0)     if(P)                     //依照P来设立校验位    { #if (PARITYBIT ==ODD_PARITY)        TB8 =0;               //设立校验位为0 #elif (PARITYBIT ==EVEN_PARITY)        TB8 =1;               //设立校验位为1 #endif    }    else    { #if (PARITYBIT ==ODD_PARITY)        TB8 =1;               //设立校验位为1 #elif (PARITYBIT ==EVEN_PARITY)        TB8 =0;               //设立校验位为0 #endif    }     busy= 1;     SBUF=ACC;                //写数据到UART数据寄存器 } void SendString(char*s) {    while(*s)                 //检测字符串结束标志    {        SendData(*s++);        //发送当前字符    } } 记不住可以看手册!! #include"reg51.h" #include"intrins.h" typedef unsigned charBYTE; typedef unsignedint  WORD; #define FOSC11059200L #define BAUD115200 sfrAUXR=0x8e;   //辅助寄存器 sbit P22=P2^2; bit busy; void SendData(BYTEdat); void SendString(char*s); void main() {      SCON=0x50;      AUXR=0x40;//设立定期器T1为1T,即一种机器周期模式      TMOD=0x20;      TL1=(256-(FOSC/32/BAUD));      TH1=(256-(FOSC/32/BAUD));      TR1=1;      ES=1;      EA=1;      SendString("Hello");      while(1); } void Uart() interrupt 4using 1 {      if(RI)      {             RI=0;             P0=SBUF;      }      if(TI)      {             TI=0;             busy=0;      } } void SendData(BYTEdat) {      while(busy);      busy=1;      SBUF=dat; } void SendString(char*s) {      while(*s)      {             SendData(*s++);      } } 五、              外部中断使用 #include sbit L1=P0^0; int main(){ IT0=1;//IT0=1,下降沿触发外部中断0,IT0=0边沿触发 EX0=1;//使用外部中断0 EA=1; while(1){        } } void Ex_int0() interrupt 0 //外部中断优先级最高 { P2=((P2&0x1f)|0x80); L1=~L1; P2=(P2&0x1f); }      其中,外部中断引脚控制是P3^2,P3^3,即相应独立按键S5,S4。 六、              实时时钟DS1302使用 蓝桥杯提供函数,解释为: 里面命令和写入数据可以看芯片手册: 左侧READ、WRITE分别是读写命令,BIT7-BIT0是要写入数据,依照需要进行配备。DS1302只需记住这两个函数即可:Write_Ds1302( , )与Read_Ds1302(x),配备看手册。 重点:芯片表阐明:第一行:秒->由于秒范畴是0-59,因此6,5,4位表达秒十位,3,2,1,0表达个位,十位最大是5,因此三位即可。 第二行:跟上面同样; 第三行:7位:1为12小时制,0为24小时制;5位:12小时制时为0表达上午,1表达下午,24小时制时,和4位一起表达小时十位; 别的时间同样表达。 倒数第二行:只看7位:为1时禁止写数据,因此开始写数据时必要置0; 读数时: !!需要加“写操作这一行代码”。 读话直接按照命令读即可。 DS1302进阶(BCD码转换):解决之前60秒不能进位问题。 1)写入初始值时,要把10十进制数转换为BCD码, 例:写入时间->17:58:50 Ds1302_Single_Byte_Write(0x8e,0x00);//写操作 Ds1302_Single_Byte_Write(0x85,((17/10)<<4 |(17)));//写时    Ds1302_Single_Byte_Write(0x83,((58/10)<<4 |(58)));//写分 Ds1302_Single_Byte_Write(0x81,((50/10)<<4 |(50)));//写秒 Ds1302_Single_Byte_Write(0x8e,0x80);//写保护 即转换公式是:((Value/10)<<4 | (Value)),可以写一种settime()函数。 2 )读数:读回来数要进行转换成十进制数 ((ReadValue&0x70)>>4)*10 +(ReadValue&0x0F); 八进制转十进制-> ReadValue=Ds1302_Single_Byte_Read(0x85);          hour=((ReadValue&0x70)>>4)*10 +(ReadValue&0x0F);    !!(这句一定不要省)     Ds1302_Single_Byte_Write(0x00,0x00);//写操作          ReadValue=Ds1302_Single_Byte_Read(0x83);          minute=((ReadValue&0x70)>>4)*10 +(ReadValue&0x0F);          Ds1302_Single_Byte_Write(0x00,0x00);//写操作          ReadValue=Ds1302_Single_Byte_Read(0x81);          sec=((ReadValue&0x70)>>4)*10 +(ReadValue&0x0F);          Ds1302_Single_Byte_Write(0x00,0x00);//写操作 显示:         dspbuf[0]=hour/10;          dspbuf[1]=hour;          dspbuf[2]=minute/10;      dspbuf[3]=minute;          dspbuf[4]=sec/10;          dspbuf[5]=sec; 七、              PCF8591与IIC总线使用 (1)   IIC总线使用: 比赛提供了IIC两个库文献,IIC.h;IIC.c,其中需要注意函数是: 其中,该函数是初始化,当使用AD转换时候需要在main函数开始时调用,该函数内部只需看这句代码即可:i2c_sendbyte(0x03);//ADC通道3,板上有4个模仿输入口,分别为0,1,2,3;设立哪一种模仿输入口就是依照这句代码,0x03表达通道3,这是依照芯片手册配备,如图: 8位前6位不用管,都为0,最后两位就是配备选取哪一种通道。 第二个函数: 读取AD转换后数值,这个函数直接调用就可以了,函数内部如何实现不用管,但是需要注意是:该函数扫描调用最佳是100ms。 第三个函数,上面都是AD转换,即模仿信号转数字信号,下面这个函数是DA转换,数字信号转换成模仿信号,就是单片机输出数字信号,用万能表去量单片机引出引脚,量一下电压大小,这个预计比赛不会考,但是防止万一: 该函数和上面两个函数分离开来,一、二函数是要在一起使用,初始化后之后才干调用,第三个加入头文献,直接调用即可,比较简朴!! 上面说法有误,A/D转换初始化函数和读取转换后数值都需要自己写。 这里理解一下PCF8591只需依照时序格式发送地址字节和控制字节:,这是地址字节,其中A2,A1,A0硬件已经接地,故都为0,最低位表达是你要从IIC总线上读数还是写数据,1表达读,0表达写,即读数据发地址是:0x91;写数据发地址是0x90; 控制字节: 由芯片资料知,控制字节有8位,有两位固定是0,除了第0、1位需要自己设立,其她咱们都设为0,那些位都是某些详细功能,咱们暂时用不着,不用管先,第0、1位是模仿通道选取,PCF8591上提供了4路模仿通道,依照需求进行选取,如选取通道3即发送控制字节:0x03; 地址字节和控制字节都明白了,接下来依照时序规定进行配备,A/D转换需要一种初始化函数:Init_ADpcf8591();和一种获得AD转换后数值函数:adc_pcf8591();其中初始化函数作用是发送AD转换控制字节;adc_pcf8591()发送读获得地址并读回数据,先写指令才干读;格式如下: 这个是初始化合同:分别是startIIC、(地址写)发送0x90、等待应答、发送控制字节(AD这里是选取通道指令,如选取通道3,0x03)0x03、等待应答、(达到目,没有后续操作,直接停止总线)StopIIC. 初始化函数就是如此写; adc_pcf8591合同: 依次是:startIIc、发送读地址0x91、等待应答、读回AD转换后数值、读回后发送应答给PCF8591,表达收到,并且不需要再返回应答,要传参数1,如图红圈示,即函数Ack(1);、最后stopIIC总线。 D/A转换(其实挺麻烦,先前太自信了,哈): 所谓D/A转换其实就是把数字信号转换成模仿信号输出,用单片机发数字通过D/A转换成电压输出,检测办法可以用电压表测量。 配备办法跟A/D类似,先发地址字节,再发控制字节,然后把数字发出去(AD这里是接受模仿信号,是相反机制)。 控制字节: 如图示,控制字节第6位是1话是模仿输出模式,别的位全为0,发送格式跟AD同样: 代码如一开始图示。 (2)   EEPROM使用,AT24C02,可以掉电仍旧保存上一次操作数据,下次上电后接着运营。 需要注意两个函数,一种是写进EEPROM里面保存,再次上电再从里面读回来: 其中写函数需要指定AT24C02地址以及需要写入数据,读函数要想取回写进数据,需要从相似地址里面读: 其中AT24C02存储地址是0x00,可以是其她地址,如0x02,但是读和写地址必要一致。 写与读合同与AD或DA相似, 由芯片资料及原理图知EEPROM(AT24C02)写地址为0xa0;读地址为0xa1;注意:读数时候读出一种数之后发送一种应答信号,若ACK(0)表达还想继续读下一种字节,若ACK(1);则不想再读数,让EEPROM停止发送。 八、              DS18B20时钟芯片使用 比赛有提供代码,只需记住这个函数: 读取温度值,整数(其中,提示EA总中断要打开、关闭,也可以不用)。 浮点数表达。 注意,只有提供函数,没有提供读取温度函数,即上面那个,只有下面:这几种函数。 编写读取温度函数需要记住DS13B20三条指令,0xCC,跳过ROM检测;然后启动温度转换:0x44;转换需要时间,这里精准延时Delay_OneWire(200);然后再次初始化,再次执行跳过,然后读取温度指令:0xBE.;注意读出温度是低字节先,然后才是高字节,分别用两个变量保存还要通过公式转换成咱们需要整数或浮点数。完整代码如上图示。 九、              超声波传感器使用 #include"reg52.h"  //定义51单片机特殊功能寄存器 #include "intrins.h" #include "absacc.h" //12M用这个 //11.0592用这个 #define somenop{_nop_();_nop_();_nop_();_nop_();_nop_();                 _nop_();_nop_();} sbit TX =P1^0;  //发射引脚 sbit RX =P1^1;  //接受引脚 code unsigned char tab[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,\                             0xff}; unsigned char dspbuf[8] ={10,10,10,10,10,10,10,10};  //显示缓冲区 unsigned char dspcom =0; unsigned int intr =0; bit s_flag; unsigned int t = 0; voidsend_wave(void); void display(void); void main(void) {    unsigned int distance;     TMOD|= 0x11;  //配备定期器工作模式     TH0= (65536-)/256;     TL0= (65536-)%6;     TH1= 0;     TL1= 0;     EA =1;     ET0= 1;  //打开定期器0中断     TR0= 1;  //启动定期器      while(1){               if(s_flag)        {            s_flag = 0;                                  t = TH1;                      t <<= 8;                      t |= TL1;                      distance = (unsigned int)(t*0.017);//计算距离                                         }               TH1 = 0;               TL1 = 0;        }                                    dspbuf[5] = distance/100;        dspbuf[6] = distance0/10;        dspbuf[7] =distance;          } } //定期器0中断服务函数 voidisr_timer_0(void)  interrupt 1 //默认中断优先级 1 {     TH0= (65536-)/256;     TL0= (65536-)%6;  //定期器重载     display();//2ms执行一次 if(++intr == 200){        s_flag = 1;        intr = 0;    } } //显示函数 void display(void){       XBYTE[0xE000] = 0xff;  //去除鬼影       XBYTE[0xC000] = (1<<dspcom);       XBYTE[0xE000] = tab[dspbuf[dspcom]]; if(++dspcom == 8){              dspcom = 0; }      } //TX引脚发送40KHz方波信号驱动超声波发送探头 void send_wave(void) { unsigned char i =8;  //发送8个脉冲 do {        TX = 1;        somenop;        TX = 0;        somenop; } while(i--); } 必要时还可以加个看门狗:   WDT_CONTR=0x34; 十、              步进电机与直流电机使用 参照代码如下: #include sbit A1=P1^4;//定义步进电机连接端口 sbit B1=P1^3; sbit C1=P1^2; sbit D1=P1^1; void qudong1(); #define Dy_A1{A1=1;B1=0;C1=0;D1=0;}//A相通电,其她相断电 #define Dy_B1{A1=0;B1=1;C1=0;D1=0;}//B相通电,其她相断电 #define Dy_C1{A1=0;B1=0;C1=1;D1=0;}//C相通电,其她相断电 #define Dy_D1{A1=0;B1=0;C1=0;D1=1;}//D相通电,其她相断电    //采用1相励磁 #define Dy_OFF{A1=0;B1=0;C1=0;D1=0;}//所有断电 unsigned charSpeed,Speed1; void DelayUs2x(unsigned chart) {   while(--t); } void DelayMs(unsigned chart) {     while(t--) {     //大体延时1mS     DelayUs2x(245);    DelayUs2x(245); } } main() { Dy_OFF; for(;;) {    qudong1();   } } void qudong1() { unsigned inti=470;//旋转一周时间 Speed=5; while(i--)  //正向 {             Dy_A1                //遇到Coil_A1  用{A1=1;B1=0;C1=0;D1=0;}代替     DelayMs(Speed);         //变化这个参数可以调节电机转速,                             //数字越小,转速越大,力矩越小     Dy_B1                              //顺序从A1--D1相通电如果为正转,那么顺序从D1--A1相通电则为反转     DelayMs(Speed);     Dy_C1     DelayMs(Speed);     Dy_D1     DelayMs(Speed);   } Dy_OFF i=512; while(i--)//反向   {     Dy_D1               //遇到Coil_A1  用{A1=1;B1=0;C1=0;D1=0;}代替     DelayMs(Speed);        //变化这个参数可以调节电机转速,                           //数字越小,转速越大,力矩越小     Dy_C1     DelayMs(Speed)
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服