关于我写的程序啥都不是还有脸上传的事
之前一直在用txt记笔记,但是后来因为代码太多了,所以想到了记到csdn上
下面是正文,无顺序,想到哪写到哪。
一些基础的
-在138译码器中,前3位代表5 6 7
P2=0xA0对应着1010 0000,则5 6 7为101,为1111
1011,Y5为0,则配置的是Y5C,控制P00-P07
P2=0x80对应着1000 0000,则5 6 7为100 为1111
0111,Y4为0,对应Y4C,这个是led灯
P2=0xC0对应着1100 0000,则5 6 7为110 为1111
1101,Y6为0,对应Y6C,这是打开数码管的片选端(控制是第几个显示),后面写P0为什么表示选哪几个,例:0x80就是1000
0000,第一个显示,也可以写为P2=(P2&0X1f)|0X80,0x80前面那个表示将P2.0-P2.4置为0
P2=0xE0对应着 1110 1111,则5 6 7位111为1111
1110,Y7为0,对应Y7C,这个是打开数码管的数据端(控制是显示什么数字)
sfr是定义特殊功能寄存器,单片机里面,共有两种寄存器,第一种是ROM,第二种是RAM。
1
ROM的功能:ROM的数据在程序运行的时候是不容改变的,除非你再次烧写程序,他就会改变,就像我们的书本,印上去就改不了了,除非再次印刷,这个就是ROM的原理。
2
RAM的功能:RAM就是在程序运行中,数据会随时改变的,就像我们的黑板,写上了可以擦,擦完再写上去,相当于程序运行的时候,调用ROM里面的数据进行各种运算。
共阳极数码管数据表:
1 2
| unsigned char code shuzi[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0xbf,0xff};//0-9,第10个是-,11是全灭 unsigned char code zimu[]={0x88,0x83,0xc6,0xa1,0x86,0x8e,0x89,0xc7,0x8c,0xc1};//A,b,C,d,E,F,H,L,P,U
|
常用字母段码表
数码管片选位置表(从左到右0-7):
1
| unsigned char code weizhi[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
|
数码管调用函数,前面是位置,后面是显示的东西,分为shuzi和zimu两种
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void shumaguan_shuzi(uchar a,uchar b) { delay_ms(1); P2=(P2&0X1f)|0xC0;P0=weizhi[a]; P2=(P2&0X1f)|0xE0;P0=shuzi[b]; delay_ms(1); //消隐 P2 = (P2 & 0x1f) | 0xc0; P0 = 0x00; P2 = P2 & 0x1f; } void shumaguan_zimu(uchar a,uchar b) { delay_ms(1); P2=(P2&0X1f)|0xC0;P0=weizhi[a]; P2=(P2&0X1f)|0xE0;P0=zimu[b]; delay_ms(1); //消隐 P2 = (P2 & 0x1f) | 0xc0; P0 = 0x00; P2 = P2 & 0x1f; }
|
配置所有引脚
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| void allinit() { P2=(P2&0x1f)|0x80; P0=0xff; P2&=0x1f; P2=(P2&0x1f)|0xA0; P0 = P0 & 0XAF; P2&=0x1f; P2=(P2&0x1f)|0xc0; P0=0xff; P2&=0x1f; P2=(P2&0x1f)|0xe0; P0=0xFF; P2&=0x1f; }
|
LED灯单独亮选择
1 2 3 4 5 6 7
| unsigned char ledweizhi[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; void ledlight(uchar x) { P2=(P2&0X1f)|0x80; P0=ledweizhi[x]; }
|
定时器
定时器0,设置1s:
1 2 3 4 5 6 7 8 9
| void Init_timer0() { TMOD = 0x01; TH0 = (65535 - 50000) / 256; //50000微秒 TL0 = (65535 - 50000) % 256; EA = 1; ET0 = 1; TR0 = 1; }
|
下面是以时钟为例,写执行的内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| void Service_timer0() interrupt 1 { TH0 = (65535 - 50000) / 256; TL0 = (65535 - 50000) % 256; count++; if(count == 20) //20*50ms为1s { second++; count = 0; } if(second == 60) { minute++; second=0; } if(minute==60) { hour++; minute=0; if(hour==24) hour=0; } }
|
矩阵按键
定义引脚 1 2 3 4 5 6 7 8 9
| sbit R1=P3^0;//第一排初始化(如果跳线帽在右边,则只有最左侧一列可以控制,写这个没问题) sbit R2=P3^1;//第二排初始化 sbit R3=P3^2;//第三排初始化 sbit R4=P3^3;//第四排初始化
sbit C1=P3^4;//第一列初始化(此为从右往左数) sbit C2=P3^5;//第二列初始化 sbit C3=P4^2;//第三列初始化 sbit C4=P4^4;//第四列初始化
|
初始化矩阵键盘
1 2 3 4 5 6
| void Init()//初始化矩阵键盘 { R1=R2=R3=R4=1; C1=C2=C3=C4=1; }
|
DS18B20配置
首先是看原理图,找到DQ,连接着P14 所以先定义好DQ
1 2 3 4 5 6 7 8 9
| sbit DQ=P1^4; void dsinit() { DQ=0; Delay500us(); DQ=1; Delay500us(); }
|
温度获取:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void temperature_get() { uchar high,low; init_ds18b20(); Write_DS18B20(0xcc); Write_DS18B20(0x44);
init_ds18b20(); Write_DS18B20(0xcc); Write_DS18B20(0xbe); low=Read_DS18B20(); high=Read_DS18B20(); temp=((high<<4)|(low>>4));//不带小数点 temp2=low&0x0f*100/16;//取两位小数点 shi=temp%100/10; ge=temp%10; //int temp;uchar shi;uchar ge;int temp2;都是全局的 }
|
防抖
按下按键,语句只执行一次: 这里以R1为例
1 2 3 4 5 6 7 8 9
| if(R1==0) { delay_ms(50); if(R1==0) { //执行语句 while(R1==0); } }
|
下面是一堆delay函数
有不同时间的,应该好用,我自己试过了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| void Delay100us() //@12.000MHz { unsigned char i, j;
i = 2; j = 39; do { while (--j); } while (--i); }
void Delay500us() //@12.000MHz { unsigned char i, j;
i = 6; j = 211; do { while (--j); } while (--i); }
void delay_ms(unsigned int n) { unsigned int i=0,j=0; for(i=0;i<n;i++) for(j=0;j<123;j++); }
|
nop()的意思是一条空语句,用来延时
PCF8591
本来上课讲了,但是我一点也没听,看了这篇文章之后,就懂了,可以说是写的真好
关于iic与pcf8591
步骤:开启总线-----发送地址+写-----发送控制字节-----等待PCF8591响应-----停止总线-----重新启动总线-----发送地址+读------读取数据-----主机发送非应答信号-----停止总线
PCF8591的设备地址包括固定部分和可编程部分。可编程部分需要根据硬件引脚A0、A1和A2来设置。设备地址的最后一位用于设置数据传输的方向,即读/写位,在IIC总线协议中,设备地址是起始信号后第一个发送的字节。如果硬件地址引脚A0、A1、A2均接地,那么,PCF8591的设备的读操作地址为:0x91;而写操作地址则为:0x90。读是1,写是0
光敏传感器接到AIN1,通道1;控制寄存器应写入:0x01。
电位器Rb2接到AIN3,通道3;控制寄存器应写入:0x03。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| //ADC转换,可以带入数值 unsigned char ad(unsigned int voltage) { uint temp; uint v; int flag; IIC_Start(); IIC_SendByte(0x90); //写操作 flag=IIC_WaitAck(); //等待应答,判断对方发送的是0还是1,从而执行下一步 if(flag) return 0; IIC_SendByte(0x40); flag=IIC_WaitAck(); if(flag) return 0; IIC_SendByte(voltage_1); flag=IIC_WaitAck(); if(flag) return 0; IIC_Stop();
IIC_Start(); IIC_SendByte(0x91); //读操作 flag=IIC_WaitAck(); if(flag) return 0; temp= IIC_RecByte(); IIC_SendAck(1); IIC_Stop(); }
|
读取电压,5v电压
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| void Read_AIN3() { int voltage; int dat; IIC_Start(); IIC_SendByte(0x90); IIC_WaitAck(); IIC_SendByte(0x03);//读取的Rb2电位器,通道三,要是0x01就是光敏电阻 IIC_WaitAck(); IIC_Stop(); IIC_Start(); IIC_SendByte(0x91); IIC_WaitAck(); dat = IIC_RecByte(); IIC_WaitAck(); IIC_Stop();
voltage=dat*100/51; shumaguan_shuzi(6,voltage%100/10); shumaguan_shuzi(7,voltage%10); P2=(P2&0X1f)|0xC0;P0=weizhi[5]; P2=(P2&0X1f)|0xFF;P0=shuzi[voltage/100]+0x80; }
|
三位数显示在数码管上: 百位:dat / 100 十位:(dat % 100) / 10
个位:dat % 10
下面是转载隔壁宿舍大佬的代码,一个函数实现ADC和DAC
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| void adc_read(unsigned char ain)//在ain这里写0x01和0x03使用光敏电阻和电位器 { EA = 0; IIC_Start(); IIC_SendByte(0x90); if(!IIC_WaitAck()) { IIC_SendByte(ain); if(!IIC_WaitAck()) { IIC_Stop(); IIC_Start(); IIC_SendByte(0x91); if(!IIC_WaitAck()) { addata = IIC_RecByte(); IIC_SendAck(0); vi=(addata*100)/51; v1=vi%1000/100; v2=vi%100/10; v3=vi%10; IIC_Stop(); } } } EA = 1; } void dac_write(float dat) { int dat_2; dat_2 = dat*100*255/500; EA=0; IIC_Start(); IIC_SendByte(0X90); if(!IIC_WaitAck()) { IIC_SendByte(0X40); if(!IIC_WaitAck()) { IIC_SendByte(dat_2); if(!IIC_WaitAck()) { IIC_Stop(); } } } EA=1; }
|
读写eeprom的函数
在write_eeprom和read_eeprom时一定要中间写一个delay,要不然数据读不进去
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| void write_eeprom(unsigned char add,unsigned char date)//写入eeprom数据,前面是地址,后面是数据 { IIC_Start(); IIC_SendByte(0xa0); IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck(); IIC_SendByte(date); IIC_WaitAck(); IIC_Stop(); } unsigned char read_eeprom(unsigned char add)//读eeprom的数据,括号里面写地址 { unsigned char temp; EA = 0; IIC_Start(); IIC_SendByte(0xa0); IIC_WaitAck(); IIC_SendByte(add); IIC_WaitAck();
IIC_Start(); IIC_SendByte(0xa1); IIC_WaitAck(); temp = IIC_RecByte(); IIC_SendAck(1); IIC_WaitAck(); IIC_Stop(); EA = 1; return temp; }
|
NE555
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| unsigned int count_f = 0; unsigned char count_t = 0; unsigned int dat_f = 0; void Init_Timer() { TH0 = 0xff; TL0 = 0xff; TH1 = (65536 - 50000) / 256; TL1 = (65536 - 50000) % 256; TMOD = 0x16; ET0 = 1; ET1 = 1; EA = 1; TR0 = 1; TR1 = 1; } void Service_T0() interrupt 1 { count_f++; } void Service_T1() interrupt 3 { TH1 = (65536 - 50000) / 256; TL1 = (65536 - 50000) % 256; count_t++; if(count_t == 20) { dat_f = count_f; count_f = 0; count_t = 0; } } void display_f() { shumaguan_zimu(0,5); if(dat_f>9999) shumaguan_shuzi(3,dat_f/10000); if(dat_f>999) shumaguan_shuzi(4,dat_f/1000%10); if(dat_f>99) shumaguan_shuzi(5,dat_f/100%10); if(dat_f>9) shumaguan_shuzi(6,dat_f/10%10); shumaguan_shuzi(7,dat_f%10); }
|
以1s间隔闪烁一次,以第八届省赛的题目为例,要求每隔1s闪烁一次
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| void Init_timer0()//定时器配置 { TMOD = 0x01; TH0 = (65535 - 50000) / 256; //50ms技术 TL0 = (65535 - 50000) % 256; EA = 1; ET0 = 1; TR0 = 1; } void Service_timer0() interrupt 1//定时器0,中断 { count_b++;//全局变量 if(count_b==20)//计算了1s { count_b=0; if(mode_smg==0)//mode_smg也是全局变量 { mode_smg=1; } else if(mode_smg==1) { mode_smg=0; } } } void hour_blink()//显示小时以1s的间隔显示一次 { if(mode_smg==1) { shumaguan_shuzi(0,hour_p/10); shumaguan_shuzi(1,hour_p%10); shumaguan_shuzi(2,10); shumaguan_shuzi(3,minute_p/10); shumaguan_shuzi(4,minute_p%10); shumaguan_shuzi(5,10); shumaguan_shuzi(6,second_p/10); shumaguan_shuzi(7,second_p%10); } if(mode_smg==0) { shumaguan_shuzi(0,11); shumaguan_shuzi(1,11); shumaguan_shuzi(2,10); shumaguan_shuzi(3,minute_p/10); shumaguan_shuzi(4,minute_p%10); shumaguan_shuzi(5,10); shumaguan_shuzi(6,second_p/10); shumaguan_shuzi(7,second_p%10); } }
|
先写这么多,想到了继续补