阶段测试一
本文字数: 5.1k 阅读时长 ≈ 5 分钟
阶段测试一
1.本套测试题内容为各大公司中真实的测试题,并且这是大家第一次做希望大家认真对待,没有什么好嘱咐的就是仔细仔细再仔细。
2.做题时题目的内容可能会引起某些童鞋的身体不适,请自备风油精。
3.还有就是请自信你是可以的,士别三日当刮目相待。
4.我要的不是用这套题打败你,而是用这套题告诉你以后的道路有多少坑,我们帮你渡过这些。
5.不要怕被击倒,所有的坑都会使你更加强大,我要的是你要对自己自信。
1. 为判断字符变量c的值不是数字也不是字母时,应采用下述表达式(D)?
A、c<=48 || c>=57 && c<=65 || c>=90 && c<=97 || c>=122
B、!(c<=48 || c>=57 && c<=65 || c>=90 && c<=97 || c>=122)
C、c>=48 && c<=57 || c>=65 && c<=90 || c>=97 && c<=122
D、!(c>=48 && c<=57 || c>=65 && c<=90 || c>=97 && c<=122)
2. 一个C语言的源程序中(A)?
A、必须有一个主函数
B、可以有多个主函数
C、必须有除主函数外其它函数
D、可以没有主函数
3. 以下不能定义为用户标识符的是(D)?
A、itoa
B、Void
C、_3com
D、int
4. 若以下选项中的变量已正确定义,则正确的赋值语句是(C)?
A、x1=26.8%3;
B、1+2=x2;
C、x3=0x12;
D、x4=1+2=3;
5. 以下叙述中正确的是(C)?
A、C语言是低级编程语言
B、C语言可以不用编译就能被计算机识别执行
C、C语言以接近英语国家的自然语言和数学语言作为语言的表达形式
D、C语言出现的最晚,具有其他语言的一切优点
6. C语言中用于结构化程序设计的3种基本结构是(A)?
A、顺序结构、选择结构、循环结构
B、if、switch、break
C、for、while、do-while
D、if、for、continue
7. 在while(!x)语句中的!x与下面条件表达式等价的是(D)?
A、x!=0
B、x==1
C、x==2
D、x==0
8. 有以下程序:
int i=1,j=1,k=2;
if((j++||k++)&&i++)
printf(“%d,%d,%d\n”,i,j,k);
执行后的输出结果是(C)?
A、1,1,2
B、2,2,1
C、2,2,2
D、2,2,3
9. 有以下程序:
int i,s=0;
for(i=1;i<10;i+=2)
s+=i+1;
printf(“%d\n”,s);
程序执行后的输出结果是(D)?
A、自然数1~9的累加和
B、自然数1~10的累加和
C、自然数1~9中奇数之和
D、自然数1~10中偶数之和
10. 下列运算表达式中哪个选项的含义不同(B)?
A、a+=1;
B、a+1;
C、a++;
D、++a;
11. 以下说法正确的是(C)?
A、C语言程序总是从第一个函数开始执行
B、在C语言程序中,要调用函数必须在main()函数中定义
C、C语言程序总是从main()函数开始执行
D、C语言程序中的main()函数必须放在程序的开始部分
12. C语言中不合法的字符串常量是(B)?
A、”\121”
B、’y’
C、”\n\n”
D、”ABCD\x6d”
13. 下述关于break语句的描述中,(C)是不正确的。
A、break语句可用于循环体内,它将退出该循环
B、break语句可用于switch语句中,它将退出switch语句
C、break语句可用于if体内,它将退出if语句
D、break语句在一个循环体内可以出现多次
14. 下面有关for循环的正确描述是(D)。
A、for循环只能用于循环次数己经确定的情况
B、for循环是先执行循环体语句,后判定表达式
C、在for循环中,不能用break语句跳出循环体
D、for循环体语句中,可以包含多条语句,但要用花括号括起来
15. 如执行以下语句,for (I=1;I<=100;I++){sum=sum+I;}循环结束后I值是(C)。
A、99
B、100
C、101
D、102
16. 在下面的函数声明中运行的结果是(AD)?
int i = 10, j = 10;
while(–i && j–);
printf(“i = %d j = %d\n”, i, j);【多选题】
A、i = 0
B、i = 1
C、j = 0
D、j = 1
17. 在下列定义中,哪种定义符合C语言标准(ACD)?【多选题】
A、_A
B、case
C、_1A
D、Int
18. 若有以下语句,则求偶数的表达式正确的是(BCD)?【多选题】
A、x % 2 != 0
B、!(x%2)
C、x%2==0
D、!(x&0x01)
19. 以下描述正确的选项是(ABD)?【多选题】
A、十进制整数13的八进制是15
B、十六进制数字0x14的八进制是24
C、二进制1100100的八进制是145
D、八进制数字64的十进制数是52
20. 若有下列程序
int a = 10, b = 20;
while(a–)
{
b -= –a;
}
printf(“a = %d b = %d\n”, a ,b);则执行结果是(AD)?【多选题】
A、a = -1
B、a = 0
C、b = -1
D、b = 0
21. C语言描述“x和y都大于或等于z”的表达式是:
x >= z && y >= z
22. sizeof关键字是一个?
运算符
23. 专门用于测试数据类型所占用的字节数的运算符是?
sizeof
24. C语言用来实现循环的结构化语句除了for、while、do…while以外还有哪个关键字?
goto
25. 若x和n都是int型变量,且x和n的初值都是6,则计算表达式x+=n++后,x的值为?
12
26. 若x和n都是int型变量,且x和n的初值都是7,则计算表达式x+=n++后,n的值为?
8
27. 在C语言中唯一的一个三目运算符是(写出中文名字)
条件运算符
28. char ch = ‘a’ + ‘8’ - ‘3’;printf(“%d”, ch);打印出的结果是多少?
102
29. int a,b,d = 241;a = d / 100 % 9;b = (-1);printf(“%d,%d\n”,b,a);程序的输出结果是多少?
-1,2
30. 已知有定义char c = -100;请表示在内存中是如何存储的c变量?
10011100
31. 设x为int型变量,则执行以下语句后x = 10;x += x -= x - x;x的值为?
20
32. 已知int x=5,y=5,z=5;执行语句x %= y + z;之后x的值是?
5
33. 下列程序执行后的输出结果是int x = ‘f’;printf(“%d\n”,’A’+ ( x - ‘a’ +1));
71
34. 有以下程序int x = 0,y = 0,z = 0;++x || ++y || ++z;printf(“%d %d %d\n”,x,y,z);执行后输出结果是
1 0 0
35. 已知int i = 10;执行表达式i >= 20 - i;之后,i的值是?
10
36. 已知int x = 1,y;执行下述语句后打印输出的是?y = (++x > 5) && (++x < 10);printf(“x = %d y = %d\n”, x, y);
x = 2, y = 0
37. int x = 0,y = 1;执行表达式(!x || y–)之后再执行printf(“x = %d y = %d\n”, x, y);打印输出的结果是?
x = 0, y = 1
38. 有以下程序int a = -1,b = 1;if((++a < 0) && !(b– <= 0)) printf(“%d %d\n”,a,b);else printf(“%d %d\n”,b,a);执行后输出结果是?
1 0
39. 有以下程序
int m = 5;
if(m++ > 5)
printf(“1 %d\n”,m);
else
printf(“2 %d\n”,m–);
执行后输出结果是?
2 6
40. 以下程序的输出结果是i
nt a = 0,b = 1,c = 0,d=20;
if(a)
d = d - 10;
else if(!b)
if(!c)
d = 15;
else
d = 25;
printf(“d = %d\n”,d);
答案:20
41. C语言的变量必须先定义再使用。对
对
错
42. _ya是不合法的C语言标识符。错
对
错
43. C语言是一种结构化程序设计语言。对
对
错
44. 在C语言中,数据类型的长度排列顺序为:char<int<long。对
对
错
45. while语句构成的循环不能用其他语句构成的循环来代替。错
对
错
46. C语言的数组是在内存中分配连续的存储单元。对
对
错
47. 运算符/和%要求参加运算的对象均为整型变量。错
对
错
48. C语言认为名为Student和student的变量是不同变量。对
对
错
49. do-while语句构成的循环只能用break语句退出。错
对
错
50. int类型的变量可以存储浮点类型的数据。错
对
错
51. 大家都知道在linux下一切皆文件,那么在linux中文件类型都有哪些?请尽可能的详细描述都有哪些文件?
普通文件 链接文件 目录文件 管道文件 网络套接字文件 字符设备文件 块设备文件
52. 请描述suid sgid 和 sticky的特点
给命令加权限,所有用户执行命令以所有者执行,sgid修改文件所属组,sticky使用户在目录中只能删除自己创建的文件,不能删除其它文件
53. 在无符号16位的环境中计算表达式0xF8 << 3得到的结果通过不同的进制表示(二进制 八进制 十进制 十六进制)
11111000000 3700 1984 7c0
54. 已知有一32bit的寄存器GPIOA_BASE,如果想要把该寄存器的第18 19位清零其他位保持不变如何操作?
GPIOA_BASE &= ~(3 << 18);
55. 已知有一32bit的寄存器GPIOA_BASE,如果想要把该寄存器的第15-12位赋值成1010其他位保持不变应该如何操作?
GPIOA_BASE &= ~(15 << 12);//清零
GPIOA_BASE |= (10 << 12);
56. 设计一套程序求1000000-1001000以内的所有素数
#include <stdio.h>
int main (void)
{
int i = 0, j = 0;
for(i = 1000000; i < 1001000; i++)
{
for(j = 2; j < i; j++)
{
if(i % j == 0)
{
break;
}
}
if(i == j)
{
printf ("%d\n",i);
}
}
return 0;
}
57. 假设有一个池塘,里面有无穷多的水。现在有2个空水壶,容积分别为5升和6升,如何只用这2个空水壶从池塘里取出3升的水。
函数指针操作实例
本文字数: 564 阅读时长 ≈ 1 分钟
第一种用法
1 | #include <stdio.h> |
第二种用法
1 | #include <stdio.h> |
stm32_note_22day
本文字数: 578 阅读时长 ≈ 1 分钟
============================
2022-9-15
============================
一.物联网云服务器
短距无线通信的模块->nRF模块、WiFi
华为物联网中->云、管、端
物联网云服务器
YeeLink 出现比较早的物联网云服务器
ESLink 东方瑞通自己的物联网云服务器
企业用户(各大公司、医院、高校)
Ocean Connect 华为物联网云服务器
小米IoT 小米物联网云服务器
AIoT 阿里物联网云服务器
百度天工 百度物联网云服务器
移动物联网云服务器
...
ESLink
ESLink
私有的物联网云服务器
iot.embsky.com
stm32_note_阎同学的窗口看门狗
本文字数: 1.8k 阅读时长 ≈ 2 分钟
除非递减计数器的值在T6位变成0前被刷新,看门狗电路在达到预置的时间周期时,
会产生一个MCU复位。在递减计数器达到窗口寄存器数值之前,如果7位的递减计
数器数值(在控制寄存器中)被刷新, 那么也将产生一个MCU复位。这表明递减计数器需要在一
个有限的时间窗口中被刷新
========================================================
递减计数器T6位变成0前刷新——当递减计数器的值小于 0x40产生复位。
递减计数器达到窗口寄存器数值之前不能被刷新
如果启动了看门狗并且允许中断,当递减计数器等于0x40时产生早期唤醒中断(EWI),
它可以被用于重装载计数器以避免WWDG复位
========================================================
如果看门狗被启动(WWDG_CR寄存器中的WDGA位被置’1’), 并且当7位(T[6:0])递减计数器从
0x40翻转到0x3F(T6位清零)时,则产生一个复位。如果软件在计数器值大于窗口寄存器中的数
值时重新装载计数器,将产生一个复位。
==========================================================
WWDG_CR寄存器中的WDGA位被置’1’启动看门狗
递减计数器从0100 0000-->0011 1111会产生一个复位
计数器值大于窗口寄存器中的数值时重新装载计数器会产生一个复位
必须定期地写入WWDG_CR寄存器,必须在1111 1111(0XFF)和1100 0000(0XC0)之间
只有当计数器值小于窗口寄存器的值时,才能进行写操作。
==========================================================
递减计数器处于自由运行状态,即使看门狗被禁止,递减计数器仍继续递减计数。当看门
狗被启用时,T6位必须被设置,以防止立即产生一个复位。
T[5:0]位包含了看门狗产生复位之前的计时数目;复位前的延时时间在一个最小值和一个最
大值之间变化,这是因为写入WWDG_CR寄存器时,预分频值是未知的。
配置寄存器(WWDG_CFR) 中包含窗口的上限值:要避免产生复位,递减计数器必须在其值
小于窗口寄存器的数值并且大于0x3F时被重新装载,图155描述了窗口寄存器的工作过程。
另一个重装载计数器的方法是利用早期唤醒中断(EWI)。设置WWDG_CFR寄存器中的WEI
位开启该中断。当递减计数器到达0x40时,则产生此中断,相应的中断服务程序(ISR)可以
用来加载计数器以防止WWDG复位。在WWDG_SR寄存器中写’0’可以清除该中断。
注: T6位可以被用来产生一个软件复位(WDGA位被置位,T6位清零)
==========================================================
看门狗被启用时,T6位必须被设置
寄存器(WWDG_CFR) 中包含窗口的上限值递减计数器必须在
其值小于窗口寄存器的数值并且大于0x3F时被重新装载
WWDG_CFR寄存器中的WEI位开启该中断,到达0x40时产生中断(ISR)可以用来加载计数器
在WWDG_SR寄存器中写’0’可以清除该中断。
控制寄存器(WWDG_CR)
0~7位有效
7号位控制看门狗的开启与关闭
0:禁止看门狗
1:启用看门狗
6号位至0时产生中断
配置寄存器(WWDG_CFR)
0~9位有效
9: 提前唤醒中断
此位若置1,则当计数器值达到40h,即产生中断。
此中断只能由硬件在复位后清除。
7、8;时基预分频器的时基可根据如下修改:
00: CK计时器时钟(PCLK1除以4096)除以1
01: CK计时器时钟(PCLK1除以4096)除以2
10: CK计时器时钟(PCLK1除以4096)除以4
11: CK计时器时钟(PCLK1除以4096)除以8
0~6: 7位窗口值
这些位包含了用来与递减计数器进行比较用的窗口值。
状态寄存器(WWDG_SR)
0位有效
0: 提前唤醒中断标志
当计数器值达到40h时,此位由硬件置1。
它必须通过软件写’0’来清除。对此位写’1’无效。
若中断未被使能,此位也会被置’1’。
在总线图里知WWDG的时钟频率位36MHz
stm32_note_18day
本文字数: 1.8k 阅读时长 ≈ 2 分钟
============================
2022-9-7
============================
一.RTC
1.RTC的简介
RTC叫做Real Time Clock,也叫做实时时钟
在市面上的芯片中,有些芯片内部集成了RTC的外设功能,有些芯片没有集成
我们使用的STM32F103RBT6芯片中集成了RTC的外设功能
(STM32F407ZGT6芯片中集成了RTC的外设功能)
RTC在STM32F103RBT6芯片中属于定时器的外设资源(属于其他定时器)
RTC可以为程序员提供万年历的功能(可以提供年 月 日 星期 时 分 秒的数据)
既然RTC属于定时器的资源
无论何种定时器,都是由 时钟频率 和 计数值 决定定时长短的
2.查找RTC的时钟频率
1)通过时钟树的分析可以了解到
可以为RTC提供时钟频率的时钟源一共有三种
(LSE LSI 和 HSE/128)
但是已知LSI是给独立看门狗(IWDG)提供时钟频率的
HSE是给锁相环(PLL)提供基础时钟频率的
所以会选择LSE为RTC提供时钟频率的
2)通过芯片手册中有关RTC的介绍
RTC选择了有LSE提供时钟频率,会把LSE先进过分频再进行使用
需要经过0x7FFF(32767)分频
---------------------------------------------------------------
问题 : 为什么不是32768分频
因为硬件默认会把分频系数加1,目的是为了防止程序员写0分频
---------------------------------------------------------------
3.查找RTC的计数值范围
1)通过芯片手册中有关RTC的介绍
RTC使用了两个16位的寄存器来存储RTC的计数值
存储的计数值是从当前时间到基准时间的秒数
----------------------------------------------------
例如 : 当前时间是2022年9月7日 星期三 10:05:20
RTC的计数值是
从1970年1月1日 00:00:00到当前时间的秒数
从1970年 - 2021年所有的秒数(平年 闰年)
从2022年1月 - 2022年8月所有的秒数(平年 闰年)
2022年9月1日 - 2022年9月6日所有的秒数
2022年9月7日00时 - 2022年9月7日10时所有的秒数
2022年9月7日10时0分 - 2022年9月7日10时5分所有的秒数
2022年9月7日10时5分0秒-2022年9月7日10时5分20秒所有秒数
----------------------------------------------------
STM32F103的官方固件只提供了
RTC_SetCounter : 设置计数值(秒数)
需要先把当前时间到基准时间的秒数求出
RTC_GetCounter : 获取计数值(秒数)
需要把读出的计数值根据基准时间转换成年月日时分秒
----------------------------------------------------
struct time_st
{
int Y;
int M;
int D;
int W;
int h;
int m;
int s;
};
4)通过芯片的手册了解RTC
为了保证RTC在主设备断电的情况下仍然可以正常工作
需要连接纽扣电池
问题1.怎么判断是第一次操作RTC?
可以在备份寄存器中存储特定的数据进行判断
============================
作业
1.把今天讲过的内容完整的复习一遍
2.把STM32F407开发板的RTC搞定
3.推进STM32F407开发板的项目工程
4.推进最终项目
============================
stm32_note_20day
本文字数: 382 阅读时长 ≈ 1 分钟
===========================
2022-9-9
===========================
开发板俯视图
Nrf通信框架
Nrf硬件图
Nrf的工作模式
SPI协议
Nrf硬件原理图
带边缘计算的项目框架
stm32_note_19day
本文字数: 345 阅读时长 ≈ 1 分钟
stm32_note_21day
本文字数: 6.6k 阅读时长 ≈ 6 分钟
============================
2022-9-13
============================
一.温故知新
短距无线通信模块->nRF24L01
接口->SPI接口
SPI一共有4条线
(CSN<片选>\SCK<时钟线>\MOSI<主出从入>\MISO<主入从出>)
全双工的工作模式
nRF可以实现一对一的通信,也可以实现一对多的通信
最多是一对六的通信->有6个接收数据的通道
在不同的频道下可以实现多对多的通信
二.短距无线通信模块
WiFi模块->使用的芯片型号是ESP8266(是乐鑫公司的芯片)
本身也是一个32bit的单片机芯片
只不过乐鑫公司在生产ESP8266芯片时在内部已经烧写了TCP/UDP的协议栈
ESP8266的接口是USART/UART的接口需要连接到我们开发板的USART2上
USART2_TX PA2
USART2_RX PA3
需要通过STM32的USART2为ESP8266模块发送AT指令(WiFi\GPRS\NB-IoT)
AT指令集

AT指令使用示例
单连接 TCP Client
ESP8266单连接

1.设置WiFi模式
"AT+CWMODE=1\r\n"
需要接收"OK"
如果设置成单连接 TCP Client可以修改成=1
注意 :
=1 softAP模式
=2 station模式
=3 softAP+station模式
2.连接路由
"AT+CWJAP="SSID","password"\r\n"
需要接收"OK"
注意 :
1)
SSID 是路由器的名称
password 是路由器的密码
2)
路由器的名称不能是中文,也不能有空格
尽量是大小写英文字母
3)
路由器的密码必须要有
4)
在小范围之内WiFi信号会有干扰,有可能会影响实验
3.查询设备 IP 地址
"AT+CIFSR\r\n"
注意 :
1)只需要有查询的指令发送即可,不需要接收查询的结果
4.ESP8266 作为 client 连接到 TCP server
"AT+CIPSTART="TCP","IP",PORT\r\n"
需要接收"OK"
注意 :
1)
IP 指的是Server端的IP地址(PC机获取的IP)
PORT 指的是Server端的端口号(可以自己设置)
5.发送数据
"AT+CIPSEND=4\r\n"
首先需要接收"OK"
然后需要接收'>'
在'>'之后写上你要发送的数据
发送完数据之后,需要接收"SEND OK"
注意 :
1)
=4 代表将来要发送4bytes数据(不算'\0')
2)
如果算上'\0'
=6 "Hello"会造成忙等
6.接收数据
"+IPD,n:xxxxxxxxxx"
注意 :
1)
n 代表的是接收到数据的字节数
2)
xxxx 代表的是接收到的数据
7.断开 TCP 连接
"AT+CIPCLOSE\r\n"
注意 :
1)只需要发送断开连接的指令,不需要接收应答
透传模式
ESP8266透传
1.在连接完TCP Server端之后需要使能透传模式
"AT+CIPMODE=1\r\n"
需要接收"OK"
2.发送数据
"AT+CIPSEND\r\n"
首先需要接收"OK"
然后需要接收'>'
在'>'之后写上你要发送的数据
注意 :
1)在透传模式下不需要指定发送数据的字节数
3.退出发送数据
"+++"
代表要退出发送数据
4.断开 TCP 连接
"AT+CIPCLOSE\r\n"
注意 :
1)只需要发送断开连接的指令,不需要接收应答
=============================
任务
1.把STM32F103开发板上的TCP client连接调通
2.组内找同学把STM32F103开发板上的固定远端的UDP通信调通
3.组内找同学把STM32F407开发板上的TCP client连接调通
=============================
esp8266.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#ifndef __ESP8266_H
#define __ESP8266_H
/*
ESP8266模块是WIFI无线通讯模块,该模块是串口接口
连接到了我们开发板上的USART2
*/
#include "stm32f10x_conf.h"//包含该头文件所有的外设头文件均已包含
typedef void (*wifi_recv_handler)(char *buf, int len);//通过typedef定义函数指针类型
extern void set_wifi_recv_handler(wifi_recv_handler h);//设置wifi接收到数据的回调函数
extern void esp8266_init(void);//初始化的函数(初始化串口)
extern void esp8266_link_wifi(char *ssid, char *passwd);//连接路由(需要路由的名称和路由的密码)
extern void esp8266_connect(char *ip, char *port);//连接TCP server
extern void esp8266_disconnect(void);//断开TCP连接
extern void esp8266_send(char *msg, char *len);//发送数据
extern void dataHandler(unsigned char c);//处理接收到的数据
#endif
esp8966.c
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include "esp8266.h"
#include "usart2.h"
#include "delay.h"
#include "stdio.h"
#include "stdlib.h"
#define O_F 1//O的状态
#define K_F 2//K的状态
static int flag = O_F;
static int ok_flag = 0;
static int len = 0;//保存数据长度的整数
//"+IPD,13:1234567890ABC"
#define ADD_S 0//+的状态
#define I_S 1//I的状态
#define P_S 2//P的状态
#define D_S 3//D的状态
#define H_S 4//,的状态
#define LEN_S 5//长度的状态
#define DATA_S 6//数据的状态
static int data_flag = ADD_S;//默认是+的状态
wifi_recv_handler wifi_handler = NULL;
void set_wifi_recv_handler(wifi_recv_handler h)//设置wifi接收到数据的回调函数
{
wifi_handler = h;
}
void dataHandler(unsigned char c)//处理接收到的数据
{
static char len_buf[5];//接收到数据的字节数
static int i = 0;//循环变量
static char data_buf[512];//存储接收到的数据
switch(data_flag)
{
case ADD_S :
if(c == '+')
data_flag = I_S;
break;
case I_S :
if(c == 'I')
data_flag = P_S;
else
data_flag = ADD_S;
break;
case P_S :
if(c == 'P')
data_flag = D_S;
else
data_flag = ADD_S;
break;
case D_S :
if(c == 'D')
data_flag = H_S;
else
data_flag = ADD_S;
break;
case H_S :
if(c == ',')
data_flag = LEN_S;
else
data_flag = ADD_S;
break;
case LEN_S ://+IPD,13:1234567890ABC
if(c == ':')
{
len_buf[i] = '\0';
len = atoi(len_buf);
data_flag = DATA_S;
i = 0;
break;
}
else
len_buf[i] = c;
i++;
break;
case DATA_S:
data_buf[i] = c;
i++;
if(i == len)
{
i = 0;
data_flag = ADD_S;
if(wifi_handler)
wifi_handler(data_buf, len);
break;
}
break;
}
if(c == '>')
ok_flag = 1;
if(ok_flag == 0)
{
switch(flag)
{
case O_F :
if(c == 'O')
flag = K_F;
break;
case K_F :
if(c == 'K')
{
flag = O_F;
ok_flag = 1;
}
else
flag = O_F;
break;
}
}
}
void esp8266_init(void)//初始化的函数(初始化串口)
{
usart_2_init();
}
void esp8266_link_wifi(char *ssid, char *passwd)//连接路由(需要路由的名称和路由的密码)
{
//AT+RST\r\n 重启无线模块
usart_2_send_data("AT+RST\r\n");
delay_ms(2000);//重启之后延时两秒
//AT+CWMODE=1\r\n 选择wifi模式
ok_flag = 0;
usart_2_send_data("AT+CWMODE=1\r\n");//选择模式
while(ok_flag == 0);//等待esp8266的OK
//AT+CWJAP="SSID","password"\r\n 连接路由
ok_flag = 0;
usart_2_send_data("AT+CWJAP=");
usart_2_send_byte('"');
usart_2_send_data(ssid);
usart_2_send_byte('"');
usart_2_send_byte(',');
usart_2_send_byte('"');
usart_2_send_data(passwd);
usart_2_send_byte('"');
usart_2_send_data("\r\n");
while(ok_flag == 0);
//AT+CIFSR\r\n 查询分配到的IP地址(必须要查一下,否则无法建立连接)
usart_2_send_data("AT+CIFSR\r\n");
}
void esp8266_connect(char *ip, char *port)//连接TCP server
{
//AT+CIPSTART="TCP","192.168.3.116",8080\r\n 建立TCP连接
ok_flag = 0;
usart_2_send_data("AT+CIPSTART=");
usart_2_send_byte('"');
usart_2_send_data("TCP");
usart_2_send_byte('"');
usart_2_send_byte(',');
usart_2_send_byte('"');
usart_2_send_data(ip);
usart_2_send_byte('"');
usart_2_send_byte(',');
usart_2_send_data(port);
usart_2_send_data("\r\n");
while(ok_flag == 0);
}
void esp8266_disconnect(void)//断开TCP连接
{
//AT+CIPCLOSE\r\n 断开TCP连接
usart_2_send_data("AT+CIPCLOSE\r\n");
//注意:有可能回复有可能不回复,所以不检测closed ok
}
void esp8266_send(char *msg, char *len)//发送数据
{
//AT+CIPSEND=4\r\n 发送数据
ok_flag = 0;
usart_2_send_data("AT+CIPSEND=");
usart_2_send_data(len);
usart_2_send_data("\r\n");
while(ok_flag == 0);//等待 OK
ok_flag = 0;
while(ok_flag == 0);//等待 >
ok_flag = 0;
usart_2_send_data(msg);
while(ok_flag == 0);//等待 SEND OK
}
stm32_note_16day
本文字数: 2.3k 阅读时长 ≈ 2 分钟
==========================
2022-9-5
==========================
一.温故知新
串行的接口
USART/UART
USART:通用的同步异步收发器
UART:通用的异步收发器
STM32F103RBT6中有3个USART/UART
目标 :
1.把USART1的所有项目实验调通
USART1的发送一个字节
USART1的发送多个字节
USART1接收(轮询和中断)一个字节数据
USART1解析接收到的字符串数据
把标准输入和标准输出重定向到USART1中
1)使用Micro Lib 2)禁用半主机模式
2.举一反三
把USART1的项目实验移植到USART2/USART3
I²C
1.分析I²C的协议
2. 驱动E²PROM OLED SHT30
3.带着大家把E²PROM驱动起来
4.大家把官方提供的OLED的案例移植到项目工程中
5.大家自己搞定SHT30
================================
任务
1.把USART1的项目实验移植到USART3上
2.工业物联网的控制终端的发送器(把相应的指令发送给设备,设备进行解析)
3.所有同学以组为单位,两两之间串一遍I²C的协议
4.系统中的界面
1)公司的LoGo
2)DHT11的数据(客厅的数据).
3)SHT30的数据(卧室的数据)
4)高精度可调电阻->虚拟成任意类型的传感器->可燃气的含量(厨房的数据)
5)额外的传感器
6)日历
7)时间
-------------------------------------------
计秒表 + 看门狗监测系统 + 界面可以通过按键切换
================================
二.ADC
1.ADC的实验
1)STM32F103RBT6开发板->高精度可调电阻->可以当做任意类似的传感器
->在扩展IO中可以连接其他的模拟型传感器
2)STM32F407ZGT6开发板->PM2.5->CO传感器
->在扩展IO中可以连接其他的模拟型传感器
3)在STM32F407开发板上查找扩展IO中有没有DAC功能的管脚,尝试驱动DAC
2.ADC的简介
在市面上有很多种类的传感器,可以分为数字型的传感器和模拟型的传感器
数字型的传感器:采集到的就是数字量,可以直接交给CPU来处理
模拟型的传感器:采集到的是模拟量,需要通过AD转换,
转换成了数字量,再交给CPU来处理
ADC : 模数转换器(可以把模拟量转换成数字量)
很多的工程师会把ADC当作电压表进行使用
3.了解STM32F103RBT6芯片上的ADC
打开<STM32RBT6\DataSheet\STM32>目录下
<ST_MCU最新选型手册.pdf> P22
通过最新选型手册的了解
1)STM32F103RBT6芯片内部已经集成了ADC
2)ADC的资源 16 x 12bit
打开<STM32RBT6\DataSheet\STM32>目录下
<STM32F103RB.pdf> P19
通过讲硬件的手册了解
1)STM32F103RBT6芯片中只有2个ADC的外设(ADC1和ADC2)
2)这两个ADC都连接到了APB2总线上
3)这两个ADC都可以使用这16个转换通道
※打开<STM32课程SDK\DataSheet\STM32>目录下
<STM32F405OE_STM32F405OEY6TR_STM32F405OG_STM32F405OGY6TR_to_STM32F407ZGT7.pdf> P18
通过讲硬件的手册了解
1)STM32F407芯片中只有3个ADC的外设(ADC1 ADC2 ADC3)
2)这三个ADC都连接到了APB2总线上
3)24个通道中其中有8个通道是ADC1 ADC2 ADC3共用
4)24个通道中其中有8个通道是ADC1 ADC2共用
5)24个通道中其中有8个通道是ADC3使用
12bit指的是量化位
把模拟量转换成数字量所占用的位数就是量化位
将来转换之后最小值是 : 0000 0000 0000 0
将来转换之后最大值是 : 1111 1111 1111 4095
※在ADC中也有LSB的概念
LSB->指的是一个量化位代表的模拟量
----------------------------------------
例子
4bit的量化位可以转换0V - 3.3V
0000 代表 0V
1111 代表 3.3V
LSB(一个量化位)0001,代表的电压值是多少?
LSB = 0.22V
----------------------------------------
4.通过芯片的手册了解ADC
打开<STM32RBT6\DataSheet\STM32>目录下
<STM32F10x中文参考手册.pdf> P113
5.开发板原理图中高精度可调电阻的连接
ADC_VOL PC0/ADC_IN10
PC0管脚将来配置为模拟输入功能