当前位置: 首页 > news >正文

嵌入式开发硬件——单片机

1、单片机最小系统

单片机外部:

电源

时钟:12M晶振,1/(2*6)分频【决定工作效率】

复位:(强制重启)

单片机内部:

RAM(随机存储器):掉电数据丢失,运行在这里。访问速率快

ROM(只读存储器):掉电数据不丢失,文件保存在这里,访问速率慢

2、51相关知识

有电势差(1v-2v),led灯才能亮

原理图:表示器件的逻辑连接关系;PCB:表示器件的物理连接关系

电容:滤波作用

电阻:负载作用,限制电流,排阻(104表示 10的3次方)

3、流水灯

时钟周期:12M hz

机器周期:

1M hz(主频)

void Delay_ms(unsigned int num)		
{unsigned char i, j;while(num--){i = 2;j = 199;do{while (--j);} while (--i);}
}
4、数码管

array[]里面存储的是0123456789abcdef,表示的数码管的abcdefg横线的1和0

digit_select()控制数码管显示的位置:

1、0x7  0000 0111>>2=0001 1100   1110 0011   代表p2.2 p2.3 p2.4端口为0

2、将digit(0-7)左移2位,存入P2.2-P2,4,其他位不变

练习:输入四位数字,显示该四位数字

#include<reg51.h>
void Delay_ms(unsigned int num)		
{unsigned char i, j;while(num--){i = 2;j = 199;do{while (--j);} while (--i);}
}
void digit_select(unsigned char digit)
{unsigned char num=P2;num &= ~(0x7<<2);num |=(digit<<2);P2=num;
}
unsigned char array[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void digit_show_num(unsigned int num)
{unsigned char digit[4];unsigned  int i;digit[3]=num%10;digit[2]=(num/10)%10;digit[1]=(num/100)%10;digit[0]=num/1000;for(i=0;i<4;i++){digit_select(i);P0=array[digit[i]];Delay_ms(5);}
}
void main(void)
{unsigned int dat=1234;while(1){digit_show_num(dat);};
}
5、8*8点阵模块

74HC595(串转并)模块

特点:8位串行输入,8位串行或并行输出,100MHZ的移位频率,输出寄存器可以直接清除

p35控制移位,p36控制输出

行数控制移位,列数控制哪个灯亮

行数高电平,列数低电平,灯亮

消影

SRCLK=0;SRCLK=1;上升沿,把每一位数据数据寄存器的数据移位

RCLK=0;RCLK=1;上升沿,把移位寄存器的数据给数据存储寄存器

SER

练习:滚动显示0-9

#include <reg51.h>
sbit RCLK = P3^5;//表示取P3端口的第5位,不是异或
sbit SRCLK = P3^6;
sbit SER = P3^4;
unsigned char code h_data[10 * 8] = 
{0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00,0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x7E, 0x7E, //数字10x00, 0x3c, 0x08, 0x10, 0x20, 0x3c, 0x00, 0x00,//数字20x00, 0x3c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x3c, //数字30x00, 0x04, 0x04, 0x04, 0x04, 0x3c, 0x04, 0x04, //数字40x3C, 0x20, 0x20, 0x3C, 0x04, 0x04, 0x3C, 0x00,  // 数字50x00, 0x3c, 0x20, 0x20, 0x3c, 0x24, 0x3c, 0x00,  //数字60x00, 0x3c, 0x04, 0x08, 0x08, 0x08, 0x08, 0x00, //数字70x7E, 0xC3, 0xC3, 0x7E, 0xC3, 0xC3, 0xC3, 0x7E,  //数字80x00, 0x18, 0x24, 0x24, 0x1C, 0x04, 0x24, 0x18 //数字9
};
void delayn(unsigned char n)
{while(n--);
}
void write_74hc595(unsigned char dat)
{unsigned char i = 0;for(i = 0; i < 8; i++){if(dat & (1 << (7 - i)))// 检查当前位是否为1{SER = 1;}else{SER = 0;}SRCLK = 0;   delayn(1);SRCLK = 1;delayn(1);      }RCLK = 0;delayn(1); RCLK = 1;
}
void main(void)
{unsigned char i = 0;unsigned char j = 0;unsigned char k = 0;unsigned char num = 0;while(1){
//首列(h_data[j])会被显示 80 次,其他列(h_data[j+1]~h_data[j+7])显示 20 次。if(j % 8 == 0)num = 80;elsenum = 20;for(k = 0; k < num; k++)//显示很多遍{for(i = 0; i < 8; i++){write_74hc595(1 << (7 - i));	 P0 = ~h_data[i + j];//共阳极,低电平有效delayn(100);P0 = 0xff; // 消除残影}}j++;if(j > 72)//上面有i+jj = 0;}
}
6、独立按键模块

注意点:

LED模块显示的数字是从右往左看,且亮灯代表0,不亮灯代表1

比如:

0x23(0010 0011),led显示应为:

1100 0100

不亮,不亮,亮,亮,亮,不亮,亮,亮

!(P3 & (1<<3))        记住

1<<3 0000 0001   0000 1000

P3=0XB0  1011 0000

1011 0000  &  0000 1000 一假则假

0000 0000

取反 1111 1111

代码:

void main()
{while(1){if(!(P3 & (1<<3)))//代表得到P33P2=0X23;elseP2=0Xff;if(!(P3 & (1<<2)))P2=0Xbb;}
}
7、矩阵按键模块

重点,有些许没搞懂

代码:

unsigned char get_key_value(void) {unsigned char col, row_val;// 扫描 4 列(P1.0-P1.3)for (col = 0; col < 4; col++) {P1 = ~(1 << col);  // 当前列置低电平,其他列高电平if ((P1 & 0XF0) != 0xF0) {  // 如果有按键按下(行不全为1)// 检测具体哪一行被按下,并控制 P2 输出if (!(P1 & (1 << 4))) P2 = ~(0x10 >> col);  // 第1行if (!(P1 & (1 << 5))) P2 = ~(0x0C >> col);  // 第2行if (!(P1 & (1 << 6))) P2 = ~(0x08 >> col);  // 第3行if (!(P1 & (1 << 7))) P2 = ~(0x04 >> col);  // 第4行}}return 0;
}
void main()
{unsigned char key=0;unsigned char dst=0;while(1){key=get_key_value();if(key!=0){dst=key;}}
}
 8、外部中断

程序顺序执行时,产生中断,要去执行中断服务程序,然后再回来执行原程序

51单片机5个中断源的优先级:

详见如图:

代码:实现按k3数字增加,k4数字减小

#include<reg51.h>
sbit SRCLK=P3^6;  //11 SRCLK管脚
sbit RCLK=P3^5; //12 RCLK管脚
sbit SER=P3^4; //14 SER管脚
unsigned char code h_data[10 * 8] = 
{0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00,0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x7E, 0x7E, //数字10x00, 0x3c, 0x08, 0x10, 0x20, 0x3c, 0x00, 0x00,//数字20x00, 0x3c, 0x04, 0x04, 0x3c, 0x04, 0x04, 0x3c, //数字30x00, 0x04, 0x04, 0x04, 0x04, 0x3c, 0x04, 0x04, //数字40x3C, 0x20, 0x20, 0x3C, 0x04, 0x04, 0x3C, 0x00,  // 数字50x00, 0x3c, 0x20, 0x20, 0x3c, 0x24, 0x3c, 0x00,  //数字60x00, 0x3c, 0x04, 0x08, 0x08, 0x08, 0x08, 0x00, //数字70x7E, 0xC3, 0xC3, 0x7E, 0xC3, 0xC3, 0xC3, 0x7E,  //数字80x00, 0x18, 0x24, 0x24, 0x1C, 0x04, 0x24, 0x18 //数字9
};
void delay(unsigned char i)//延时函数
{while(i--);
}
void Hc595pro(unsigned char dat) //发送段选数据函数
{unsigned char a=0;for(a=0;a<8;a++){if(dat&(1<<(7-a))){SER=1;}else{SER=0;}SRCLK=0;delay(1);SRCLK=1;delay(1);}RCLK=0;RCLK=1;
}
void enit0_init(void)
{IT0=1;EA=1;EX0=1;
}
void enit1_init(void)
{IT1=1;EA=1;EX1=1;
}
unsigned char num=0;
void enit0_hanlder(void) interrupt 0
{P2=0X0f;if(num<9)num++;P2=~num;                     
}
void enit1_hanlder(void) interrupt 2
{P2=0Xf0;if(num>0)num--;P2=~num;                     
}
void main()
{unsigned char key = 0;unsigned char k = 0;unsigned char i = 0;unsigned char dst = 0;unsigned char j = 0;unsigned char abs = 0;enit0_init();enit1_init();while(1)		   // 0   4    8  {for(j = 0; j <= abs; j++){for(k = 0; k < 30; k++){for(i = 0; i < 8; i++){Hc595pro(1 << (7 - i));P0 = ~h_data[i + num * 8];delay(100);P0 = 0xff;}}}	}
}
9、定时器/计数器

计时器/定时器的核心部件是一个加法计数器

1、16位定时器最大计数值65535,所以初值 =65535-50000=15536=0x3caf

2、TMOD &= ~(0x1<<2);清除TMOD的第2位(bit2)

3、TMOD &= ~(0x1<<3);清除TMOD的第3位(bit3)

4、TMOD &= ~(0x3<<0);         TMOD |= (0x01<<0);

这两行代码组合起来实现了:

先清零TMOD的bit0和bit1(M1和M0)

然后设置M0=1,M1=0

代码:实现时间显示

#include <reg51.h>
unsigned char array[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71,0x40};
unsigned char sec = 0;  
void delay_ms(unsigned int num)
{unsigned char i, j;while(num--){i = 2;j = 199;do{while (--j);} while (--i);}
}
void timer0_init(void)
{TH0=0x4c;  //(65535-50000)/256;0x3cTL0=0x00;  //(65535-50000)%256;0cafTMOD &=~(0X1<<2);//设置计数器的时钟来源TMOD &=~(0X1<<3);//GATE设置为0//设置模式为16位定时器TMOD &=~(0X3<<0);TMOD |=(0X01<<0);ET0=1;EA=1;TR0=1;
}
void timer0_hanlder(void) interrupt 1
{static unsigned char timer0_num= 0;TH0=0x4c;	//(65535-50000)/256;TL0=0x00;	//(65535-50000)%256;	TR0=1;timer0_num++;if(20==timer0_num)//20*50ms=1s{	sec++; timer0_num=0;}	
}
void  digit_select(unsigned char digit,unsigned char seg)  // 0~7
{unsigned char num = P2;num &= ~(0x7 << 2);	    num |= (digit << 2);P2 = num;P0=seg;	   
}
void main(void)
{unsigned char hour = 23;unsigned char min = 55; timer0_init();while(1){if(60==sec){min++;sec=0;if(60==min){hour++;min=0;if(24==hour){hour=0;}}}      digit_select(0,array[sec%10]);delay_ms(2);digit_select(1,array[sec/10]);delay_ms(2);		digit_select(2,array[16]);		delay_ms(2);digit_select(3,array[min%10]);delay_ms(2);digit_select(4,array[min/10]);delay_ms(2);digit_select(5,array[16]);delay_ms(2);		digit_select(6,array[hour%10]);		delay_ms(2);digit_select(7,array[hour/10]);delay_ms(2);}	
}
10、串口通信

单工,半双工,全双工?

并行:一次性全部传输(两根及以上的数据线)

串行:一个一个传输(一根数据线)

同步:通信双方使用同一个时钟

异步:通信双方使用不同的时钟

波特率:单位时间内传输的码元数(比特率)

小tips:

电压是两点之间的电势差,必须两点都有电压

串行口控制寄存器:PCON和SCON

11、DS18B20

DS18B20 采用单总线通信协议,初始化是主机(MCU)与从机(DS18B20)建立通信的第一步。核心步骤如下:

主机发送复位脉冲:拉低总线至少480µs,然后释放(高电平)。

从机响应存在脉冲:DS18B20 检测到上升沿后,等待15-60µs,拉低总线60-240µs作为应答。

总线恢复空闲:从机释放总线,主机检测到应答后确认设备在线。

写0

  • 主机拉低总线 60µs~120µs,释放总线,进入恢复时间。
  • 从机在主机拉低后的 15µs~30µs 窗口内采样总线

写1:

  • 主机拉低总线 1µs~15µs(短暂脉冲)。
  • 从机快速释放总线,总线被上拉电阻拉高

读0/1:

  • 主机拉低总线 ≥1µs(启动读时间片),在15µs内释放总线并切换为输入模式(高阻态),在拉低后的 15µs~30µs 窗口内读取总线电平(低="0",高="1")
  • 若从机发送"0":主动拉低总线并保持至时间片结束(图中 DS1820 active low,若发送"1":不动作,总线由上拉电阻维持高电平

上课认真听,不要依赖于视频,不懂知识点记下来,自学给它搞懂

看一遍代码,再独立自己写

http://www.lryc.cn/news/613574.html

相关文章:

  • Mac 电脑安装 ADB 环境完整指南
  • windows操作系统定时关机、重启指令记录
  • vue3对比vue2的性能优化和提升 :Vue 3 vs Vue 2
  • 重学React(三):状态管理
  • windows内核研究(内存管理-线性地址的管理)
  • Java集合的遍历方式(全解析)
  • 0807 IO线程的同步互斥
  • latex in overleaf快速通关论文排版
  • FPGA学习笔记——VGA显示静态图片(ROM IP核)
  • 【数据结构入门】双向链表
  • 深入理解 S7-200 SMART 的 “数据语言”:从位到字符串的格式密码
  • C++线程库的学习
  • 【JS】扁平树数据转为树结构
  • 蓝桥杯----数码管、按键、定时器与中断
  • 【感知机】感知机(perceptron)学习算法的收敛性
  • 代码随想录算法训练营 Day20
  • Redis面试精讲 Day 13:Redis Cluster集群设计与原理
  • P1037 [NOIP 2002 普及组] 产生数
  • NFS 服务器
  • Docker容器强制删除及文件系统修复完整指南
  • mysql的InnoDB索引总结
  • 传统防火墙与下一代防火墙
  • 中介效应分析 原理解释 实例分析
  • python中的集合
  • 移动端录屏需求调研:以小熊录屏为例的轻量级实现方案
  • 线程池创建线程
  • jmeter要如何做接口测试?
  • Jmeter使用第一节-认识面板(Mac版)
  • 【线性代数】5特征值和特征向量
  • Vue3获取当前页面相对路径