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

串口通信 day48

单片机

一:基础概念

一:单片机最小系统

单片机:电源+时钟(晶振)+复位 //实现的最小组件

电源:5V直流

时钟(晶振):决定系统运行的速率 一般12M(不超过50M),因为过快导致稳定性,抗干扰性能下降,

​ 分为分频和倍频,一般都是分频(1/(2*6)分频)

复位:电平信号(高/低) 2种:先上升沿,在下降沿; 先下降沿,后上升沿

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

PCB:表示器件物理连接关系

二:RAM/ROM 芯片自带

RAM :随机存储器 (访问速度快) 4kb //掉电数据丢失

ROM :只读存储器 (访问速度慢) 100~200kb //掉电数据不丢失

三:发光二极管

单个二极管要求电压:0.5v~0.7v 一般给1v~2v 电流:10mv~MAX

四:流水灯

#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 main(void)
{unsigned char dat = 0;while(1){P2 = 255 - dat++; //共阳极delay_ms(500);};
}

五:显示数字

#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);  //22 23 24 控制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 long num)
{unsigned char digits[8];int i = 0;  for (i = 7; i >= 0; i--) {digits[i] = num % 10;num /= 10;}while(1){for(i=0;i<8;i++){if(digits[i] != 0){digit_select(7 - i);P0 = array[digits[i]]; delay_ms(2);        }}}
}void main(void)
{ digit_show_num(65536);	//51单片机是8位系统,所以要long int	
}

六:74HC595(串转并)模块,点亮8*8LED点阵

信号名(简写)全称功能说明对应引脚
SERSerial Data串行数据输入(Data)14
SRCLK / SPCLKShift Register Clock移位寄存器时钟(移位控制)11
RCLKRegister Clock (Latch Clock)锁存时钟(控制输出)12
SRCLRShift Register Clear清除寄存器10
OEOutput Enable输出使能,低电平有效13
#include <reg51.h>
#include <intrins.h>sbit SER  = P3^4;
sbit SHCP = P3^6;
sbit STCP = P3^5;
sbit BEEP = P2^5;void delay_us(unsigned char us)
{while(us--){_nop_(); _nop_(); _nop_(); _nop_(); // 4×NOP指令,大概1us}
}void shift_out(unsigned char dat)
{unsigned char i;for(i = 0; i < 8; i++){SHCP = 0;SER = (dat & 0x80) ? 1 : 0;dat <<= 1;delay_us(1);	//如果移的太快,可能导致芯片识别不到上升沿SHCP = 1;delay_us(1);   //如果移的太快,可能导致芯片识别不到上升沿}//最后再产生一个上升沿STCP = 0;delay_us(1);STCP = 1;
}void main(void)
{while(1){BEEP = 0;shift_out(0xff);P0 = 0x00;delay_us(100);P0 = 0xFF;}
}
#include <reg51.h>
#include <intrins.h>sbit SER  = P3^4;
sbit SHCP = P3^6;
sbit STCP = P3^5;
sbit BEEP = P2^5;void delay_us(unsigned char us)
{while(us--){_nop_(); _nop_(); _nop_(); _nop_(); // 4×NOP指令,大概1us}
}void shift_out(unsigned char dat)
{unsigned char i;for(i = 0; i < 8; i++){SHCP = 0;SER = (dat & 0x80) ? 1 : 0;dat <<= 1;delay_us(1);	//如果移的太快,可能导致芯片识别不到上升沿SHCP = 1;delay_us(1);   //如果移的太快,可能导致芯片识别不到上升沿}//最后再产生一个上升沿STCP = 0;delay_us(1);STCP = 1;
}unsigned char xin_shape[8] = {0x99,0x00,0x00,0x00,0x81,0xC3,0xE7,0xFF
};void main(void)
{int i = 0;while(1){for(i = 0;i<8;i++){shift_out ((1 << i) ); // 列数据(高电平表示点亮)P0 = xin_shape[7-i];          delay_us(100);P0 = 0xFF;  //消影 	}	BEEP = 0;}
}
#include <reg51.h>
#include <intrins.h>sbit SER  = P3^4;
sbit SHCP = P3^6;
sbit STCP = P3^5;
sbit BEEP = P2^5;void delay_ms(unsigned int num)
{unsigned char i,j;while(num--){i = 2;//看具体晶振大小j = 199;}do{while(--j);}while(--i);
}void delay_us(unsigned char us)
{while(us--){_nop_(); _nop_(); _nop_(); _nop_(); // 4×NOP指令,大概1us}
}void shift_out(unsigned char dat)
{unsigned char i;for(i = 0; i < 8; i++){SHCP = 0;SER = (dat & 0x80) ? 1 : 0;dat <<= 1;delay_us(1);	//如果移的太快,可能导致芯片识别不到上升沿SHCP = 1;delay_us(1);   //如果移的太快,可能导致芯片识别不到上升沿}//最后再产生一个上升沿STCP = 0;delay_us(1);STCP = 1;
}unsigned char num_font_0_9[10 * 8] = {0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00, // 00x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x7E, 0x7E, // 10x7E, 0x42, 0x42, 0x06, 0x1C, 0x30, 0x60, 0x7E, // 20x7E, 0x42, 0x42, 0x1C, 0x1C, 0x42, 0x42, 0x7E, // 30x0C, 0x1C, 0x2C, 0x4C, 0x7E, 0x7E, 0x0C, 0x0C, // 40x7E, 0x60, 0x60, 0x7C, 0x06, 0x06, 0x46, 0x7E, // 50x3C, 0x60, 0x40, 0x7C, 0x66, 0x42, 0x66, 0x3C, // 60x7E, 0x42, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30, // 70x3C, 0x66, 0x66, 0x3C, 0x66, 0x42, 0x66, 0x3C, // 80x3C, 0x66, 0x66, 0x3E, 0x02, 0x06, 0x0C, 0x38  // 9
};void main(void)
{unsigned char i = 0;unsigned char j = 0;unsigned char k = 0;unsigned char num = 0;while(1){if(j % 8 == 0)num = 80;elsenum = 20;for(k = 0; k < num; k++){for(i = 0; i < 8; i++){shift_out(1 << (7 - i));	//// 0x80 0x40 0x20 0x10 0x08 0x04 0x02 0x01	 P0 = ~num_font_0_9[i + j];	//i + j 表示当前这一帧要显示的列数据delay_us(100);P0 = 0xff;}}j++;if(j > 72)j = 0;}
}

七:按键

#include <reg51.h>void main(void)
{while(1){if(!(P3 & (1 << 3)))P2 = 0x55; // 0101 0101elseP2 = 0xFF; // 1111 1111if(!(P3 & (1 << 2)))P2 = 0xaa; // 1010 1010}
}
#include <reg51.h>
sbit BEEP = P2^5;void delay_ms(unsigned int num)
{unsigned char i,j;while(num--){i = 2;//看具体晶振大小j = 199;}do{while(--j);}while(--i);
}unsigned char code seg_table[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07,  // 0~70x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71   // 8~F
};void main(void)
{unsigned char i = 0;unsigned char j = 0;unsigned char key = 0;while(1){BEEP = 1;for(i = 0;i<4;i++){P1 = ~(P1 & (1 << i));for(j = 0;j<4;j++){if(!(P1 & (1 <<j+4))){key = 4*(3-j)+(3-i);P0 = seg_table[key];delay_ms(500);while(!(P1 & (1 <<j+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)  // 0~7
{unsigned char num = P2;num &= ~(0x7 << 2);	    num |= (digit << 2);P2 = num;	   
}// 点阵数据(10个数字图案,每个8字节)
unsigned char code h_data[10 * 8] = 
{0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00,	// 00x18, 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
};// 段码(未用,可保留)
unsigned char array[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71};// 74HC595 引脚
sbit RCLK = P3^5;
sbit SRCLK = P3^6;
sbit SER = P3^4;// 简单延时
void delayn(unsigned char n)
{while(n--);
}// 发送1字节数据到74HC595
void write_74hc595(unsigned char dat)
{unsigned char i = 0;for(i = 0; i < 8; i++){SER = (dat & (1 << (7 - i))) ? 1 : 0;SRCLK = 0;   delayn(1);SRCLK = 1;delayn(1);      }RCLK = 0;delayn(1); RCLK = 1;
}// 外部中断0初始化
void eint0_init(void)
{IT0 = 1;    // 下降沿触发EX0 = 1;    // 开启INT0中断EA = 1;     // 开启总中断
}// 当前显示的数字
unsigned char num = 0;// 中断服务函数,显示数字 +1
void eint0_hanlder(void) interrupt 0 
{P2 = 0xf0;     // 可用于调试num++;if (num > 9)num = 0;P2 = ~num;     // 显示在 P2(可接LED)
}// 外部中断1初始化(INT1,P3.3,下降沿触发)
void eint1_init(void) {IT1 = 1;   // 1 = 边沿触发(下降沿)EX1 = 1;   // 允许外部中断1EA  = 1;   // 总中断允许(一般只需设置一次)
}// 外部中断1服务函数(中断号 2)
void eint1_handler(void) interrupt 2 {P2 = 0x0f; // 可用于调试或 LED 显示if (num == 0)num = 9;elsenum--;P2 = ~num; // 显示新的值
}// 主函数
void main(void)
{unsigned char key = 0;unsigned char k = 0;unsigned char i = 0;unsigned char dst = 0;unsigned char j = 0;unsigned char abs = 0;eint0_init();  // 初始化外部中断eint1_init();while(1)		   // 显示当前 num 指向的数字{for(j = 0; j <= abs; j++){for(k = 0; k < 30; k++){for(i = 0; i < 8; i++){write_74hc595(1 << (7 - i));             // 列选P0 = ~h_data[i + num * 8];               // 行码delayn(100);                             // 简单延时P0 = 0xff;                               // 消影}}}	}
}
二:定时器

TFO:定时器/计数器T0溢出中断标志。T0被允许计数以后,从初值开始加1计数,当最高位产生溢出时,由硬件置“1”TFO,向CPU请求中断,一直保持CPU响应该中断时,才由硬件清“O”TFO(TFO也可由程序查询清“O”)

TRO:定时器T0的运行控制位。该位由软件置位和清零。当GATE(TMOD.3)(第三位)=0,TR0=1时就允许T0开始计数,TR0=0时禁止T0计数。当GATE(TMOD.3)=1,TR1=0且INTO输入高电平时,才允许TO计数。

​ TRO=0 //停止计数

​ TRO = 1 //启动计数

​ GATE = 0 //直接计数

​ = 1 //INTO为高电平时计数

定时器/计数器工作模式寄存器TMOD:

定时和计数功能由特殊功能寄存器TMOD的控制位C/T进行选择,TMOD寄存器的各位信息如下表所列。可以看出,2个定时/计数器有4种操作模式,通过TMOD的M1和M0选择。2个定时/计数器的模式0、1和2都相同,模式3不同,各

//定时器0
#include <reg51.h>// 硬件接口定义
sbit RCLK = P3^5;
sbit SRCLK = P3^6;
sbit SER = P3^4;// 延时函数(简易版)
void delayn(unsigned char n) {while(n--);
}// 74HC595 写入一个字节
void write_74hc595(unsigned char dat) {unsigned char i;for(i = 0; i < 8; i++) {SER = (dat & (1 << (7 - i))) ? 1 : 0;SRCLK = 0;delayn(1);SRCLK = 1;delayn(1);}RCLK = 0;delayn(1);RCLK = 1;
}// 数码管图案数据(0~9)
unsigned char code h_data[10 * 8] = {0x00, 0x18, 0x24, 0x24, 0x24, 0x24, 0x18, 0x00,	// 00x18, 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
};// 全局变量
unsigned char num = 0; // 当前显示的数字// 外部中断0初始化(下降沿触发)
void eint0_init(void) {IT0 = 1;EX0 = 1;EA = 1;
}// 外部中断0服务函数
void eint0_handler(void) interrupt 0 {P2 = 0xf0; // 可用于调试num++;if (num > 9) num = 0;P2 = ~num; // 可接 LED 显示数值
}// 外部中断1初始化(INT1,P3.3,下降沿触发)
void eint1_init(void) {IT1 = 1;   // 1 = 边沿触发(下降沿)EX1 = 1;   // 允许外部中断1EA  = 1;   // 总中断允许(一般只需设置一次)
}// 外部中断1服务函数(中断号 2)
void eint1_handler(void) interrupt 2 {P2 = 0x0f; // 可用于调试或 LED 显示if (num == 0)num = 9;elsenum--;P2 = ~num; // 显示新的值
}void timer0_init(void)
{TH0 = 0x4C;TL0 = 0x00;		//15535/256TMOD &= ~(0x1<< 2);	TMOD &= ~(0x1<< 3);TMOD &= ~(0x3 << 0);TMOD |= (0x01 << 0);ET0 = 1;           // 允许定时器0中断 EA = 1;TR0 = 1;
}void timer0_handler(void) interrupt 1
{static unsigned char timer0_num = 0;TH0 = 0x4C;TL0 = 0x00;TR0 = 1;timer0_num++;if(20 == timer0_num){num++;if (num == 9)num = 0;timer0_num = 0;}
}// 主函数
void main(void)
{unsigned char key = 0;unsigned char k = 0;unsigned char i = 0;//unsigned char num = 0;unsigned char dst = 0;unsigned char j = 0;unsigned char abs = 0;eint0_init();timer0_init(); while(1)		   // 0   4    8  {for(j = 0; j <= abs; j++){for(k = 0; k < 30; k++){for(i = 0; i < 8; i++){write_74hc595(1 << (7 - i));P0 = ~h_data[i + num * 8];delayn(100);P0 = 0xff;}}}	}
}
三:24小时时钟
#include <reg51.h>unsigned char hour = 17;
unsigned char min = 59; 
unsigned char sec = 0;  unsigned char code digit_table[] = {0x3F, // 00x06, // 10x5B, // 20x4F, // 30x66, // 40x6D, // 50x7D, // 60x07, // 70x7F, // 80x6F  // 9
};void timer0_init(void)
{TH0 = 0x4C;TL0 = 0x00;		//15535/256TMOD &= ~(0x1<< 2);	TMOD &= ~(0x1<< 3);TMOD &= ~(0x3 << 0);TMOD |= (0x01 << 0);ET0 = 1;           // 允许定时器0中断 EA = 1;TR0 = 1;
}void timer0_handler(void) interrupt 1
{static unsigned char timer0_num = 0;TH0 = 0x4C;TL0 = 0x00;if(++timer0_num >= 20)  // 20×50ms = 1s{timer0_num = 0;sec++;if(sec >= 60){sec = 0;min++;if(min >= 60){min = 0;hour++;if(hour >= 24)hour = 0;}}}
}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);  //22 23 24 控制num |= (digit << 2);P2 = num;
}void digit_show_num()
{unsigned char digits[8];unsigned char i;digits[0] = hour / 10;      // 小时十位digits[1] = hour % 10;      // 小时个位digits[2] = 10;            digits[3] = min / 10;       // 分钟十位digits[4] = min % 10;       // 分钟个位digits[5] = 10;             digits[6] = sec / 10;       // 秒十位digits[7] = sec % 10;       // 秒个位for(i = 0; i < 8; i++){digit_select(i);if(digits[i] == 10)     P0 = 0x40;          elseP0 = digit_table[digits[7-i]];delay_ms(2);}
}// 主函数
void main(void)
{timer0_init();while(1){digit_show_num();delay_ms(100);} }

九:串口通信

通信:无线和有线

​ 单工 半双工 全双工

并行:多个数据线 串行:一根数据线

同步:通信双方使用同一个时钟,SPI信息帧,有CLK引脚

异步:通信双方使用不同时钟,双方要固定的数据帧(0起始,1停止)和传输速度(波特率,一般都是9600bps = 1s:单位时间传输了多少个码元,这里用二进制码元),无CLK引脚

空闲时总线保持高电平。起始信号:由高到低 起始信号:由低到高

数据位:5,6,7,8位 需要起始位:1~2位

eg:11001100 实际数据:0x33,数据头是低位

一:UART串口

#include <reg51.h>unsigned char recv = 0;unsigned char code digit_table[] = {0x06, // 10x5B, // 20x4F, // 30x66, // 40x6D, // 50x7D, // 60x07, // 70x7F, // 8
};void digit_select(unsigned char digit)
{unsigned char num = P2;num &= ~(0x7 << 2);  num |= (digit << 2);P2 = num;
}void serial_server() interrupt 4 
{if(TI)TI = 0;if(RI)RI = 0;recv = SBUF;switch(recv){case '1':digit_select(0); P0 = digit_table[0];break;case '2':digit_select(1); P0 = digit_table[1];break;case '3':digit_select(2); P0 = digit_table[2];break;case '4':digit_select(3); P0 = digit_table[3];break;case '5':digit_select(4); P0 = digit_table[4];break;case '6':digit_select(5); P0 = digit_table[5];break;case '7':digit_select(6); P0 = digit_table[6];break;case '8':digit_select(7); P0 = digit_table[7];break;default:P0 = 0xff;}}void main(void)
{
#if 1		SCON = 0x50;			TMOD &= 0x0F;		TMOD |= 0x20;		TL1 = 0xFD;	TH1 = 0xFD;		ES = 1;EA = 1;		TR1 = 1;
#endif//P0 = 0xEF;	while(1);}
http://www.dtcms.com/a/318404.html

相关文章:

  • 华清远见25072班C语言学习day3
  • EXCEL-业绩、目标、达成、同比、环比一图呈现
  • Etcd,真的需要集群部署吗?
  • 消防通道占用识别误报率↓79%!陌讯动态融合算法实战优化
  • 模 板 方 法 模 式
  • 人大金仓数据库逻辑备份与恢复命令
  • PostgreSQL报错“maximum number of prepared transactions reached”原因及高效解决方案解析
  • 百货零售行业数字化蓝图整体规划方案(165页PPT)满分可编辑PPT
  • 构建语义搜索引擎:Weaviate的实践与探索
  • XXL-JOB快速入门
  • cygwin+php教程(swoole扩展+redis扩展)
  • 【完整源码+数据集+部署教程】爬行动物异常检测系统源码和数据集:改进yolo11-GhostDynamicConv
  • 一个php 连sqlserver 目标计算机积极拒绝,无法连接问题的解决
  • 第三节 YOLOv5数据集构成
  • 集成显卡 vs 独立显卡:如何通过设备管理器识别你的GPU?
  • Docker 常用命令介绍
  • 【docker】完整 Dockerfile 示例和构建运行指南
  • 飞浆 paddleocr 识别图片上文字的角度
  • 学习 Android(十四)NDK基础
  • OpenWebUI通过pipeline对接dify的workflow
  • 滑动窗口相关题目
  • VirtualBox 搭建 Linux 虚拟机全流程:Nginx 学习环境前置配置指南
  • ##Anolis OS 8.10 安装oracle19c
  • 广州汽车配件3d打印模型加工厂家-中科米堆CASAIM
  • 【计组】存储系统
  • 3479. 水果成篮 III
  • Tiny-cuda-nn安装指南
  • CVE-2021-1879
  • Linux系统编程——环境变量、命令行参数
  • Dart语言语法与技术重点