分类 📖电子&通信 下的文章 - 我的学记|刘航宇的博客
首页
📊归档
⏳时光机
📬留言
🐾友链
资助名单
推荐
🎓843课程班
🖼️相册
🎵音乐
🏞️壁纸
搜 索
1
【NPN/PNP三极管】放大电路饱和失真和截止失真的区别
11,232 阅读
2
论文写作中如何把word里面所有数字和字母替换为新罗马字体
6,357 阅读
3
【高数】形心计算公式讲解大全
5,736 阅读
4
【1】基于STM32CubeMX-STM32GPIO端口开发
4,479 阅读
5
如何判断运放是工作在线性区还是非线性区
4,202 阅读
🌻微语&随笔
励志美文
我的随笔
写作办公
📖电子&通信
电路&嵌入式
通信&信息处理
编程&脚本笔记
🗜️IC&系统
FPGA&ASIC
VLSI&IC验证
EDA&虚拟机
💻电子&计算机
IP&SOC设计
机器学习
软硬件算法
登录
搜 索
标签搜索
嵌入式
ASIC/FPGA
VLSI
SOC设计
机器学习
天线设计
C/C++
EDA&虚拟机
小实验
软件算法
信号处理
电子线路
通信&射频
随笔
笔试面试
硬件算法
Verilog
软件无线电
Python
DL/ML
刘航宇Hangyu Liu
嵌入式系统&数字IC爱好者博客
累计撰写
296
篇文章
累计收到
522
条评论
首页
栏目
🌻微语&随笔
励志美文
我的随笔
写作办公
📖电子&通信
电路&嵌入式
通信&信息处理
编程&脚本笔记
🗜️IC&系统
FPGA&ASIC
VLSI&IC验证
EDA&虚拟机
💻电子&计算机
IP&SOC设计
机器学习
软硬件算法
页面
📊归档
⏳时光机
📬留言
🐾友链
资助名单
推荐
🎓843课程班
🖼️相册
🎵音乐
🏞️壁纸
用户登录
登录
📖电子&通信(共110篇)
找到
110
篇与
📖电子&通信
相关的结果
西北大学数字电子技术个人考研笔记
警告 若个人或辅导机构 擅自复制本文直接或间接盈利 、请向我举报,举报方式见下面,本人以 著作权法 追查! 本站域名由sciarm.com更变为ee.ac.cn 和下文页面中信息不冲突举报方式1.邮箱hyliu@ee.ac.cn2.点击博客中留言或私聊都可
2022年04月07日
1,221 阅读
0 评论
18 点赞
2022-04-07
西北大学模拟电子技术个人考研笔记
警告 若个人或辅导机构 擅自复制本文直接或间接盈利 、请向我举报,举报方式见下面,本人以 著作权法 追查到底!同时核查该机构/个人 是否有非法出书情况 、是否有 出版权与书号 , 一并交于公安机关追查 ! 本站域名由sciarm.com更变为ee.ac.cn 和下文页面中信息不冲突举报方式-请携带证据举报1.邮箱hyliu@ee.ac.cn2.点击博客中留言或私聊都可
2022年04月07日
1,418 阅读
0 评论
30 点赞
2022-03-13
数字电路基础-最大项与最小项
目录1.定义最小项:n个变量的逻辑乘,即与形式,每个变量以原变量或者反变量的形式出现一次。n个变量共有2n个最小项。用m表示,如ABC,表示为m0。最大项:n个变量的逻辑和,即或形式,每个变量以原变量或者反变量的形式出现一次。n个变量共有2n个最大项。用M表示,如A+B+C,表示为M0。如下为三变量最小项和最大项的表示方法: 2.性质对于n个变量来说,若给定这些变量确定的值,那么2n个最小项中仅有一组值为1,其余全为0;2n个最大项中仅有一组值为0,其余全为1.全部最小项之和恒等于1;全部最大项之积恒等于0。(可由第一条性质中看出)任意两个最小项之积等于0;任意两个最大项之和等于1。(可由第一条性质中看出)若干个最小项的和等于其余最小项和的反。简单可以记做为卡诺图上分成两部分,他们之间为反关系。3.关系最小项的反是最大项,最大项的反是最小项。
2022年03月13日
1,076 阅读
0 评论
6 点赞
SIM900A发送与接受短信
目录一.SMS简介SMS(Short Messaging Service)中文名称短信服务,短信是当下每一部手机上必备的功能之一,顾名思义,它是在手机之间发送文字信息或从个人计算机或手持设备向手机发送信息的一种方式,其文本信息的最大发送量为160个字符(字母、数字或者拉丁字母中的字符),对于中文一般最大发送量为70个字符。这里我想用SIM900A模块实现短信的收发。 二.短信的控制模式与编码先说一下:我采用的是Text Mode下使用GSM编码收发英文短信、使用UCS2编码收发中文短信对于短信的控制一共有三种模式:Block Mode、基于AT指令的Text Mode、基于AT指令的PDU Mode 。目前手机中默认使用PDU Mode,通过PDU编码的短信可以是文字、声音或者图像。Text Mode只能用于发送ANSI范围的字符,发送方式比较简单。SIM900A模块只提供Text Mode 和PDU Mode。中文短信中,所有汉字和字符都是采用UNICODE编码。1.Text ModeText Mode下,发送及接收到的数据均以ASCII码的显示来表示,可以发送指令"AT+CMGF=1",将GSM短信发送方式更改为文本模式。文本模式下接收的数据会自动解码,比如你收到一条短信息,GSM会返回:+CMGR: “REC UNREAD”,"+8613806XXXXXX",“11/10/21,13:22:13+32”hello (短信内容会自动换行)不需要自己解码,便可得到短信的发送者、发送时间和短信内容,比较容易操作。理论上Text Mode下,是只能够收发英文短信,但是SIM900A模块可以在Text Mode下使用UCS2编码,从而可以发送接收中文短信。2.PDU ModePDU相当于一个数据包,它由SMS的信息组成,作为一种数据单元,必须包含源地址、目的地址、有效时间、数据格式、协议类型、正文、正文长度(可达140字节),这些信息都以十六进制表示。PUD Mode被所有手机支持,可以使用任何字符集,其编码方式分为:7bit、8bit、UCS2。7-bit编码用于发送普通的ASCII字符,它将一串7-bit的字符(最高位为0)编码成8-bit的数据,每8个字符可“压缩”成7个;8-bit编码通常用于发送数据消息,比如图片和铃声等;而UCS2编码用于发送Unicode字符。在这三种编码方式下,PDU串的用户信息(TP-UD)段最大容量(可以发送的短消息的最大字符数)分别是160、140和70。这里,将一个英文字母、一个汉字和一个数据字节都视为一个字符。理论上发送中文短信需要使用PDU Mode的UCS2编码,上面也说了,SIM900A模块可以使用Text Mode发送UCS2编码,而且PDU Mode比Text Mode更加复杂,所以我采用了Text Mode收发中英文短信。PDU Mode的详细讲解可以借鉴此博客:点击链接跳转3.GSM编码在GSM编码模式下,收发消息的内容和电话号码,都是以ASCII字符的形式显示的,发送英文短信时使用十分方便。所以我使用GSM编码来收发英文短信。4.UCS2编码谈到UCS2编码就不得不说UNICODE,UNICODE又叫统一码、万国码,是计算机科学领域里的一项行业标准,包括字符集、编码方案等。UNICODE 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。简单来说,UNICODE编码可以表示世界上任意一种语言(有点夸张),自然也可以表示中文。而UCS2编码是UNICODE的一种,UCS2中每个字符都占俩个字节。使用UCS2编码后,发送短信的手机号码、短信内容都要经过UCS2编码转换才可以,但UCS2编码发送的消息在手机上可以直接显示为中文。所以,需要UCS2与中文的转换软件,如下,可以实现中文和UCS2的双向转换 三.收发英文短信1.AT+CPMS查询短信数量2.AT+CNMI设置新消息提示类型3.AT+CMGF选择短信模式4.AT+CSCS设置编码 5.AT+CSMP设置短信文本模式使用Text Mode的GSM编码时,短信文本模式设置为:AT+CSMP=17,167,0,240(消息显示在终端)AT+CSMP=17,167,0,241(消息存储在SIM卡中) 6.AT+CMGS发送消息到指定手机号使用Text Mode的GSM编码时,直接AT+CMGS="手机号"即可,然后,在>后输入要发送的内容(不要勾选发送新行),最后发送HEX(十六进制)的:1A 即可。如图,我使用本机向本机发送了一条短信,而且,本机收到短信后在终端中显示出来了。 这是SIM公司给出的例子:CTRL-Z 代表十六进制:1A使用SIM900A向本机发送一条英文短信的完整步骤如下: 四.收发中文短信收发中文短信利用的是Text Mode下的UCS2编码。相比于收发英文短信,收发中文短信需要修改的地方有:修改编码:AT+CSCS=“UCS2”修改短信文本模式:AT+CSMP=17,167,0,24(短消息显示在终端,25:存储在SIM中)手机号码要用UNICODE码发送的消息要用UNICODE码(有专门的转换软件)这是SIM公司给出的例子: 我要发送信息:可爱的小白鼠,女朋友收到后回复消息,用软件将UNICODE码转换为中文,串口操作界面如示: 发消息如示: 收消息如示: 这是我的SIM900A
2022年02月16日
610 阅读
0 评论
1 点赞
HAL_STM32_DS18B20开发
1.设置一个如PA0作为DS18B20模块接口2.添加下面2个文件,注意程序已经集成us延时ds18b20.c#include "ds18b20.h" static inline void delay_ms(uint32_t delay) { HAL_Delay(delay); } #define CPU_FREQUENCY_MHZ 72 // CPU主频,根据实际进行修改 static void delay_us(uint32_t delay) { int last, curr, val; int temp; while (delay != 0) { temp = delay > 900 ? 900 : delay; last = SysTick->VAL; curr = last - CPU_FREQUENCY_MHZ * temp; if (curr >= 0) { do { val = SysTick->VAL; } while ((val < last) && (val >= curr)); } else { curr += CPU_FREQUENCY_MHZ * 1000; do { val = SysTick->VAL; } while ((val <= last) || (val > curr)); } delay -= temp; } } //复位DS18B20 void DS18B20_Rst(void) { DS18B20_IO_OUT(); //SET PA0 OUTPUT DS18B20_DQ_OUT=0; //拉低DQ delay_us(750); //拉低750us DS18B20_DQ_OUT=1; //DQ=1 delay_us(15); //15US } //等待DS18B20的回应 //返回1:未检测到DS18B20的存在 //返回0:存在 uint8_t DS18B20_Check(void) { uint8_t retry=0; DS18B20_IO_IN();//SET PA0 INPUT while (DS18B20_DQ_IN&&retry<200) { retry++; delay_us(1); }; if(retry>=200)return 1; else retry=0; while (!DS18B20_DQ_IN&&retry<240) { retry++; delay_us(1); }; if(retry>=240)return 1; return 0; } //从DS18B20读取一个位 //返回值:1/0 uint8_t DS18B20_Read_Bit(void) // read one bit { uint8_t data; DS18B20_IO_OUT();//SET PA0 OUTPUT DS18B20_DQ_OUT=0; delay_us(2); DS18B20_DQ_OUT=1; DS18B20_IO_IN();//SET PA0 INPUT delay_us(12); if(DS18B20_DQ_IN)data=1; else data=0; delay_us(50); return data; } //从DS18B20读取一个字节 //返回值:读到的数据 uint8_t DS18B20_Read_Byte(void) // read one byte { uint8_t i,j,dat; dat=0; for (i=1;i<=8;i++) { j=DS18B20_Read_Bit(); dat=(j<<7)|(dat>>1); } return dat; } //写一个字节到DS18B20 //dat:要写入的字节 void DS18B20_Write_Byte(uint8_t dat) { uint8_t j; uint8_t testb; DS18B20_IO_OUT();//SET PA0 OUTPUT; for (j=1;j<=8;j++) { testb=dat&0x01; dat=dat>>1; if (testb) { DS18B20_DQ_OUT=0;// Write 1 delay_us(2); DS18B20_DQ_OUT=1; delay_us(60); } else { DS18B20_DQ_OUT=0;// Write 0 delay_us(60); DS18B20_DQ_OUT=1; delay_us(2); } } } //开始温度转换 void DS18B20_Start(void)// ds1820 start convert { DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc);// skip rom DS18B20_Write_Byte(0x44);// convert } //初始化DS18B20的IO口 DQ 同时检测DS的存在 //返回1:不存在 //返回0:存在 uint8_t DS18B20_Init(void) { DS18B20_Rst(); return DS18B20_Check(); } //从ds18b20得到温度值 //精度:0.1C //返回值:温度值 (-550~1250) short DS18B20_Get_Temp(void) { uint8_t temp; uint8_t TL,TH; short tem; DS18B20_Start (); // ds1820 start convert DS18B20_Rst(); DS18B20_Check(); DS18B20_Write_Byte(0xcc);// skip rom DS18B20_Write_Byte(0xbe);// convert TL=DS18B20_Read_Byte(); // LSB TH=DS18B20_Read_Byte(); // MSB if(TH>7) { TH=~TH; TL=~TL; temp=0;//温度为负 }else temp=1;//温度为正 tem=TH; //获得高八位 tem<<=8; tem+=TL;//获得底八位 tem=(float)tem*0.625;//转换 if(temp)return tem; //返回温度值 else return -tem; } ds18b20.h#ifndef __DS18B20_H #define __DS18B20_H #include "main.h" #include "stm32f1xx_hal.h" //#include "delay.h" #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) #define MEM_ADDR(addr) *((volatile unsigned long *)(addr)) #define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum)) #define GPIOA_ODR_Addr (GPIOA_BASE+12) #define GPIOB_ODR_Addr (GPIOB_BASE+12) #define GPIOC_ODR_Addr (GPIOC_BASE+12) #define GPIOD_ODR_Addr (GPIOD_BASE+12) #define GPIOE_ODR_Addr (GPIOE_BASE+12) #define GPIOF_ODR_Addr (GPIOF_BASE+12) #define GPIOG_ODR_Addr (GPIOG_BASE+12) #define GPIOA_IDR_Addr (GPIOA_BASE+8) #define GPIOB_IDR_Addr (GPIOB_BASE+8) #define GPIOC_IDR_Addr (GPIOC_BASE+8) #define GPIOD_IDR_Addr (GPIOD_BASE+8) #define GPIOE_IDR_Addr (GPIOE_BASE+8) #define GPIOF_IDR_Addr (GPIOF_BASE+8) #define GPIOG_IDR_Addr (GPIOG_BASE+8) #define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) #define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) #define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) #define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) #define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) #define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) #define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) #define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) #define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) #define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) #define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) #define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) #define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) #define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //IO方向设置 #define DS18B20_IO_IN() #define DS18B20_IO_OUT() //IO操作函数 #define DS18B20_DQ_OUT PAout(0) //数据端口 PA0 #define DS18B20_DQ_IN PAin(0) //数据端口 PA0 uint8_t DS18B20_Init(void); //初始化DS18B20 short DS18B20_Get_Temp(void); //获取温度 void DS18B20_Start(void); //开始温度转换 void DS18B20_Write_Byte(uint8_t dat);//写入一个字节 uint8_t DS18B20_Read_Byte(void); //读出一个字节 uint8_t DS18B20_Read_Bit(void); //读出一个位 uint8_t DS18B20_Check(void); //检测是否存在DS18B20 void DS18B20_Rst(void); //复位DS18B20 #endif程序进行调用使用温度=DS18B20_Get_Temp();进行调用数值,可见精度达到要求了
2022年02月03日
886 阅读
3 评论
11 点赞
2022-01-31
【10】基于STM32CubeMX-STM32ADC与OLED开发
目录实训案例:ADC与OLED综合训练在XMF07A或XMF07C开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能:【1】 上电开机后,首选在OLED上显示“强国图志”图片,然后让LED1与LED2依次点亮,然后熄灭,进行灯光检测。灯光检测结束后,OLED切换至数据显示界面,分3行:第1行显示:“ sciarm.com ”第2行显示:“采样值:”第3行显示:“电压值:”【2】在主程序中,采用查询的方式,每隔0.3秒对ADC_IN0通道的光敏传感器进行一次电压数据采集,并将采样到的12位数据换算成对应的实际电压值。LED1作为A/D采样指示灯,每采样一次闪烁一下。【3】每进行完一次光敏传感器的数据采样和电压换算后,将其结果更新到OLED显示屏中相应的位置。如果光敏传感器的电压值小于1.3V,则将LED2灯点亮,反之,将LED2灯关闭。//首先需要进行OLED的底层驱动函数移植,生成相应的文字和图片数据 /* USER CODE BEGIN Includes */ //====引入OLED底层驱动的头文件======== #include "XMF_OLED_STM32Cube.h" #include "stdio.h" /* USER CODE END Includes */extern unsigned char BMP1[]; #define LED1_ON() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9,GPIO_PIN_SET) #define LED2_ON() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8,GPIO_PIN_SET) #define LED1_OFF() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9,GPIO_PIN_RESET) #define LED2_OFF() HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8,GPIO_PIN_RESET) uint16_t ADC0_Value = 0; uint16_t ADC_Volt = 0; uint8_t str_buff[64];//LED灯流水点亮检测 void LED_Check() { LED1_ON(); HAL_Delay(500); LED2_ON(); HAL_Delay(500); LED1_OFF(); HAL_Delay(500); LED2_OFF(); HAL_Delay(500); }//显示开机LOGO图片 void OLED_display_pic() { OLED_Clear(); OLED_DrawBMP(0,0,128,8,BMP1); }//显示数据显示界面 void OLED_display_info() { OLED_Clear(); OLED_ShowString(6,0,(uint8_t *)"sciarm.com"); HAL_Delay(200); OLED_ShowCHinese(0,3,24); OLED_ShowCHinese(18,3,25); OLED_ShowCHinese(36,3,26); OLED_ShowString(54,3,(uint8_t *)":"); HAL_Delay(200); OLED_ShowCHinese(0,6,16); OLED_ShowCHinese(18,6,17); OLED_ShowCHinese(36,6,26); OLED_ShowString(54,6,(uint8_t *)":"); HAL_Delay(200); }//更新ADC采样数据与换算结果 void OLED_display_dat() { sprintf((char*)str_buff, "%4d", ADC0_Value); OLED_ShowString(64,3,(uint8_t *)str_buff); sprintf((char*)str_buff, "%d.%d%dV", ADC_Volt/100, (ADC_Volt%100/10), ADC_Volt%10); OLED_ShowString(64,6,(uint8_t *)str_buff); }//ADC采样过程与灯光自动控制 void Get_ADC0_Value() { HAL_ADC_Start(&hadc1); if(HAL_OK == HAL_ADC_PollForConversion(&hadc1, 30)) { ADC0_Value = HAL_ADC_GetValue(&hadc1); ADC_Volt = ADC0_Value * 330 / 4096; if(ADC_Volt < 130) { LED2_ON(); } else { LED2_OFF(); } } HAL_ADC_Stop(&hadc1); }/* USER CODE BEGIN 2 */ OLED_Init(); //初始化OLED OLED_display_pic(); //显示开机LOGO图片 LED_Check(); //灯光检测 OLED_display_info(); //显示数据界面 /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { LED1_ON(); //ADC采样指示灯点亮 Get_ADC0_Value(); //进行一次ADC采样及逻辑处理 OLED_display_dat(); //更新OLED中的采样数据 HAL_Delay(200); //延时0.2秒 LED1_OFF(); //ADC采样指示灯关闭 /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
2022年01月31日
776 阅读
0 评论
12 点赞
2022-01-29
【9】基于STM32CubeMX-STM32OLED开发
目录必备文件关于OLED的概述OLED:Organic Light-Emitting Display,有机发光显示。OLED具备自发光、厚度薄、视角广、功耗低、对比度高、响应速度快、可用于挠曲性面板、使用温度范围广、构造及其制作过程较简单等优异特性,并认为是一种比液晶显示更为先进的新一代平板显示技术。以目前的技术,OLED的尺寸还难以大型化,但是分辨率却可以做得很高。基于STM32的OLED应用,要做那些事情:【1】移植OLED的底层驱动函数库。【2】准备需要的中文字符和图片等数据。【3】调用OLED驱动库中的底层函数进行应用开发。OLED开发相关资源下载基于STM32CubeMX的OLED屏驱动程序库(内含4个文件)【1】XMF_OLED_STM32Cube.c:驱动程序的源文件。【2】XMF_OLED_STM32Cube.h:驱动程序的头文件。【3】XMF_OLED_Font.h:字库数据文件。【4】XMF_OLED_BMP.h:图片数据文件。基于STM32CubeMX的OLED底层驱动函数移植【1】将4个驱动文件拷贝到工程文件中,和main.c放在同一目录,并将XMF_OLED_STM32Cube.c添加到工程代码文件中,并在main.c中引入头文件XMF_OLED_STM32Cube.h。【2】根据所选用的芯片型号,修改XMF_OLED_STM32Cube.h头文件中所以用的芯片头文件。【3】根据硬件电路原理图中,修改XMF_OLED_STM32Cube.h中OLED的引脚定义。【4】查看OLED_Init(void)初始化函数的源码,根据电路接口和应用需要进行修改。OLED驱动库中常用的函数void OLED_Init(void); //OLED初始化函数 void OLED_Clear(void); //OLED清屏函数//显示英文字符串函数 void OLED_ShowString(unsigned char x,unsigned char y,unsigned char *p); 参数1:x,起点列坐标,0~127 参数2:y,起点行坐标,0~7 参数3:*p,字符串指针 返回值:void,无。//显示中文字符函数 void OLED_ShowCHinese(unsigned char x,unsigned char y,unsigned char no); 参数1:x,起点列坐标,0~127 参数2:y,起点行坐标,0~7 参数3:no,待显示中文字符在数组Hzk[][32]中的位置。 返回值:void,无。//显示图片函数 void OLED_DrawBMP( unsigned char x0, unsigned char y0,unsigned char x1,unsigned char y1,unsigned char BMP[]); 参数1:x0,起点列坐标,0~127 参数2:y0,起点行坐标,0~7 参数3:x1,图片的列范围,1~128 参数4:y1,图片的行范围,1~8 参数5:BMP[],待显示图片数据的数组。 返回值:void,无。实训案例:STM32控制OLED显示要点字库软件中行前后缀不需要括号在XMF07A或XMF07C开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能:【1】用取字模软件生产一张图片数据,作为开机界面在OLED上显示。【2】0.5秒后进入信息界面, 第1行显示网址“sciarm.com”, 第2行显示中文“小蜜蜂笔记”,第3行显示日期“2022-02-18”。//用取字模软件生成开机LOGO图片数据,并拷贝到XMF_OLED_BMP.h的数组中。 const unsigned char BMP1[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //此处省略64×62个字节元素 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, };//用取字模软件生成所需中文字符数据,保持到XMF_OLED_Font.h中的Hzk[]数组。 const unsigned char Hzk[][32]={ , ,/*"小",0*/ /* (16 X 16 , 宋体 )*/ , ,/*"蜜",1*/ /* (16 X 16 , 宋体 )*/ , ,/*"蜂",2*/ /* (16 X 16 , 宋体 )*/ , ,/*"笔",3*/ /* (16 X 16 , 宋体 )*/ , ,/*"记",4*/ /* (16 X 16 , 宋体 )*/ };extern unsigned char BMP1[]; void OLED_display_pic() { OLED_Clear(); OLED_DrawBMP(0,0,128,8,BMP1); }void OLED_display_info() { OLED_Clear(); OLED_ShowString(6,0,(uint8_t *)"sciarm.com"); OLED_ShowCHinese(10,3,0); //小 OLED_ShowCHinese(28,3,1); //蜜 OLED_ShowCHinese(46,3,2); //蜂 OLED_ShowCHinese(64,3,3); //笔 OLED_ShowCHinese(82,3,4); //记 OLED_ShowString(24,6,(uint8_t *)"2022-02-18"); }//在mian()函数中添加下面的代码: /* USER CODE BEGIN 2 */ OLED_Init(); //OLED初始化 OLED_display_pic(); //显示图片 HAL_Delay(500); //延时0.5秒 OLED_display_info(); //显示信息 /* USER CODE END 2 */
2022年01月29日
1,224 阅读
17 评论
12 点赞
2022-01-26
【8】基于STM32CubeMX-STM32ADC开发基础
目录STM32的ADC资源概述STM32F103ZE芯片(144脚)中有ADC1、ADC2、ADC3共3个12位逐次逼近型模数转换器,具有18个测量通道,可测量16个外部和2个内部信号源(内部温度和内部参考电压)。这2个内部信号源只能连接到ADC1。ADC的各个通道的A/D转换可以单次、连续、扫描或间断模式执行。A/D转换结果以左对齐或右对齐的方式,存储在16位规则组或者注入组数据寄存器中。按照A/D转换的组织形式来划分,ADC的模拟输入通道分为规则组和注入组两种。ADC可以对一组最多16个通道按照指定的顺序逐个进行转换,这组指定的通道称为规则组。在实际应用中,可能需要中断规则组的转换,临时对某些通道进行转换,好像这些通道注入了原来的规则组,故称注入组,最多由4个通道组成。ADC启动与停止相关的HAL库函数//查询,阻塞方式,启动ADC HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc); //查询,阻塞方式,停止ADC HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc); //中断,非阻塞方式,启动ADC HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc); //中断,非阻塞方式,停止ADC HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc);ADC转换结果读取的HAL库函数uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc); 参数1:hadc,ADC实例指针。 返回值:uint32_t,ADC转换结果。查询方式,阻塞式A/D转换HAL库函数HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout); 参数1:hadc,ADC实例指针。 参数2:Timeout,超时时间。 返回值:HAL_StatusTypeDef,函数执行状态。应用实例:用查询的方式,进行一次A/D采样并将结果读出。 uint16_t ADC_Value = 0; //以查询的方式启动ADC HAL_ADC_Start(&hadc); //等待一次规则组的ADC转换完成,并将结果读出 if(HAL_OK == HAL_ADC_PollForConversion(&hadc1,10)) { ADC0_Value = HAL_ADC_GetValue(&hadc1); }中断方式,非阻塞式A/D转换HAL库函数应用实例:用中断的方式,进行一次A/D采样并将结果读出。 uint16_t ADC_Value = 0; //以中断的方式启动ADC HAL_ADC_Start_IT(&hadc); //重写ADC转换完成中断回调函数 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { ADC0_Value = HAL_ADC_GetValue(&hadc1); }实训案例:ADC单次数据采样与电压换算在XMF07A或XMF07C开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能: 【1】将ADC_IN0设置为12位ADC,右对齐,启用中断。【2】分别用查询和中断这2种方式,每隔0.5秒采样一次ADC的数据。【3】将每次读取到的ADC采样值转换为对应电压值,发送到上位机。【4】LED1作为采样指示灯,在ADC转换过程中点亮,其余时间熄灭。要点配置串口没有接收中断,不需要对NVIC进行使能#include "stdio.h" #define LED1_ON() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET) #define LED1_OFF() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET) uint16_t ADC0_Value = 0, ADC0_Volt = 0; uint8_t str_buff[64];void UR1_Send_Info() { sprintf((char *)str_buff,"采样值:%d,电压值:%d.%d%dV\r\n",ADC0_Value,ADC0_Volt/100,(ADC0_Volt%100)/10,ADC0_Volt%10); HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000); }用查询,阻塞的方式来实现void Get_ADC_Value() { HAL_ADC_Start(&hadc1); LED1_ON(); if(HAL_OK == HAL_ADC_PollForConversion(&hadc1,10)) { ADC0_Value = HAL_ADC_GetValue(&hadc1); ADC0_Volt = ADC0_Value * 330 / 4096; } UR1_Send_Info(); LED1_OFF(); HAL_ADC_Stop(&hadc1); }//在mian()函数中添加以下代码: /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { Get_ADC_Value(); //启动一个阻塞式的ADC转换并读取数据 // UR1_Send_Info(); //向上位机发生采样值和电压值 HAL_Delay(500); //延时0.5秒,再进行下一次ADC采样 /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */用中断,非阻塞的方式来实现void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if(hadc->Instance == ADC1) { ADC0_Value = HAL_ADC_GetValue(&hadc1); //读取ADC转换结果 ADC0_Volt = ADC0_Value * 330 / 4096; //将采样值换算成电压值 UR1_Send_Info(); //向上位机发生ADC采样信息 LED1_OFF(); //关闭LED1采样指示灯 } }//在mian()函数中添加以下代码: /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_ADC_Start_IT(&hadc1); //启动一个非阻塞式的ADC转换并读取数据 LED1_ON(); //点亮LED1采样指示灯 HAL_Delay(500); //延时0.5秒,再进行下一次ADC采样 /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
2022年01月26日
932 阅读
1 评论
11 点赞
【7】基于STM32CubeMX-STM32ADC模数转化基本原理
目录模数转换器(ADC)概述ADC:Analog-to-Digital Converter将时间和幅值连续的模拟量转化为时间和幅值离散的数字量,A/D转换一般要经过采样、保持、量化和编码4个过程。常用ADC:逐次逼近型、双积分型、∑-Δ型。ADC的几个技术指标【1】量程:指ADC所能输入模拟信号的类型和电压范围,即参考电压。信号类型包括单极性和双极性。【2】转换位数:量化过程中的量化位数n。 A/D转换后的输出结果用n位二进制数来表示。【例】:10位ADC的输出值就是0~1023。【3】分辨率:ADC能够分辨的模拟信号最小变化量。计算公式是,分辨率 = 量程 / 2的n次方【例】:量程为单极性0-5V,8位ADC的分辨率是,5 / 256 = 0.0195V【4】转换时间:ADC完成一次完整的A/D转换所需要的时间,包括采样、保持、量化、编码的全过程。剖析ADC的基本转换过程实训案例:ADC数据采样的计算应用有一个温度测控系统,已知温度传感器在0到100度之间为线性输出,参考电压为5V,采用8为的A/D转换器,0度的时候,测的电压为1.8伏,100度的时候,测的电压为4.3伏。【问题1】:系统的分辨率是多少?【问题2】:采集到数据10010001,表示多大电压?温度是多少?由于温度是线性变化,先求得斜率k,得到温度和电压的关系表达式。k = (100 – 0)/(4.3-1.8) = 40, y = 40*(x-1.8) (x为采样得到的电压)由于采用的是8为ADC,参考电压为5V,所以分辨率为:5 / 256 = 0.0195V = 19.5mV(最小能分辨的电压,分辨率)0.0195 * 40 = 0.78度(最小能分辨的温度)因为 10010001B = 91H = 145(16x9+1), 所以 0.0195 * 145 = 2.8275V该电压信号对应的温度是:(2.83V – 1.8V) * 40 = 41.1摄氏度
2022年01月26日
476 阅读
0 评论
14 点赞
2022-01-23
【6】基于STM32CubeMX-STM32定时器与串口综合训练
目录关于sprintf()函数的用法sprintf(),指的是字符串格式化函数,把格式化的数据写入某个字符串中。int sprintf(char string, char format [,argument,…]);引入头文件 #include “stdio.h“【例】:有一个表示温度的整型变量tmp,现在要将其格式化为字符串“温度是:XX摄氏度”,并将其通过串口1发送出去。#include "stdio.h" uint8_t Str_buff[64]; sprintf((char*)Str_buff, "温度是: %d摄氏度", tmp); HAL_UART_Transmit(&huart1, Str_buff, sizeof(Str_buff), 0xFFFF);实训案例:定时器与串口综合训练配置要点时钟外设在XMF07A或XMF07C开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能:【1】开机后,LED1与LED2依次点亮,然后熄灭,进行灯光检测,高电平点亮LED灯。【2】系统通过串口1向上位机发送一个字符串“=========XMF07欢迎你!==========”。【3】LED1作为一个秒闪灯,系统向上位机发送完字符串后,开始亮0.5秒,灭0.5秒….循环闪烁,并启动系统运行时间的记录,其时分秒格式为 “XX:XX:XX”。【4】上位机通过一个由3个字节组成的命令帧控制LED2灯的开关。该命令帧的格式为 “0xBF 控制字 0xFB”。0xBF为帧头,0xFB为帧尾,控制字的定义如下:0xA1:打开LED2,返回信息 “XX:XX:XX LED2打开。”0xA2:关闭LED2,返回信息 “XX:XX:XX LED2关闭。”其他:返回信息 “XX:XX:XX 这个一个错误指令!”。#define LED1_ON() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET) #define LED2_ON() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET) #define LED1_OFF() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET) #define LED2_OFF() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET) #define LED1_TOG() HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9) #define LED2_TOG() HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8) uint8_t str1[] = "===============XMF07欢迎你!================\r\n"; uint8_t hh = 0, mm = 0, ss = 0, ss05 = 0; uint8_t str_buff[64]; uint8_t Rx_dat[16];void Ckeck_LED() { LED1_ON(); HAL_Delay(500); LED2_ON(); HAL_Delay(500); LED1_OFF(); HAL_Delay(500); LED2_OFF(); HAL_Delay(500); }void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { LED1_TOG(); ss05++; if(ss05 == 2) { ss05 = 0; ss++; if(ss == 60) { ss = 0; mm++; if(mm == 60) { mm = 0; hh++; } } } }void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { if(Rx_dat[0] == 0xBF && Rx_dat[2] == 0xFB) { switch(Rx_dat[1]) { case 0xa1: LED2_ON(); sprintf((char *)str_buff,"%d:%d:%d LED2打开!\r\n",hh,mm,ss); break; case 0xa2: LED2_OFF(); sprintf((char *)str_buff,"%d:%d:%d LED2关闭!\r\n",hh,mm,ss); break; default: sprintf((char *)str_buff,"%d:%d:%d 这是一个错误的命令!\r\n",hh,mm,ss); break; } HAL_UART_Transmit(&huart1,str_buff,sizeof(str_buff),10000); HAL_UART_Receive_IT(&huart1,Rx_dat,3); } } }//在mian()函数中添加以下代码: Ckeck_LED(); //LED灯流水检测 HAL_UART_Transmit(&huart1,str1,sizeof(str1),0xFFFF); //向上位机发送欢迎字符 HAL_UART_Receive_IT(&huart1,Rx_dat,3); //启动串口1接收上位机3个字节 HAL_TIM_Base_Start_IT(&htim2); //启动定时器TIM2
2022年01月23日
659 阅读
0 评论
11 点赞
2022-01-21
【5】基于STM32CubeMX-STM32串口数据收发
目录串行接口相关知识点并行通信、串行通信的概念。单工、半双工、全双工的概念。异步串行通信:通信双方在没有同步时钟的前提下,将一个字符(包括特定的附加位)按位进行传输的通信方式。波特率:每秒钟传输的二进制位数,如9600bps。TTL电平<—->RS232:MAX3232 SP3232串口<———>USB接口:CH340 CP2012STM32芯片的串口UASRT功能十分强大,但对于日常编程而言,使用最多的还是异步串行通信。串口1:USART1_TX与PA9复用,USART1_RX与PA10复用。串口2:USART2_TX与PA2复用,USART2_RX与PA3复用。HAL库中串口发送的重要函数////查询方式,阻塞式发送函数(初学者,推荐使用) HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size, uint32_t Timeout); 参数1:huart,串口实例的指针。 参数2:*pData,待发送数据缓冲区的指针。 参数3:Size,待发送数据的字节数。 参数4:Timeout,超时时间值。 返回值:HAL_StatusTypeDef,函数执行状态。 typedef enum { HAL_OK = 0x00U, HAL_ERROR = 0x01U, HAL_BUSY = 0x02U, HAL_TIMEOUT = 0x03U } HAL_StatusTypeDef; ////中断方式,非阻塞式发送函数 HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart,uint8_t *pData, uint16_t Size); 参数1:huart,串口实例的指针。 参数2:*pData,待发送数据缓冲区的指针。 参数3:Size,待发送数据的字节数。 返回值:HAL_StatusTypeDef,函数执行状态。 ////串口发送完毕中断回调函数 void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart); void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)应用举例:使用非阻塞式的串口发送函数,将发送缓数组dat_Txd中的前5个数据发送到USART1,在数据发送完成后,翻转PB9引脚的输出电平。 //使用中断,非阻塞方式 HAL_UART_Transmit_IT(&huart1, dat_Txd, 5); void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1); { HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9); } } //使用查询,阻塞方式 HAL_UART_Transmit(&huart1, dat_Txd, 5, 10000); HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_9);HAL库中串口接收的重要函数////查询方式,阻塞式接收函数 HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout); 参数1:huart,串口实例的指针。 参数2:*pData,数据接收据缓冲区的指针。 参数3:Size,待接收数据的字节数。 参数4:Timeout,超时时间值。 返回值:HAL_StatusTypeDef,函数执行状态。 非阻塞式接收函数(推荐使用) HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart,uint8_t *pData,uint16_t Size); 参数1:huart,串口实例的指针。 参数2:*pData,数据接收据缓冲区的指针。 参数3:Size,待接收数据的字节数。 返回值:HAL_StatusTypeDef,函数执行状态。 ////串口接收完毕中断回调函数 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);应用举例:使用非阻塞式的串口接收函数,接收USART1中的一个字节,将其保存在dat_Rxd变量中,在数据接收完成后,判断该字节,若为0x5A,则翻转PB8引脚的输出电平。 //使用中断,非阻塞方式 HAL_UART_Transmit_IT(&huart1, &dat_Rxd, 1); void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { if(dat_Rxd == 0x5A) HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8); } }实训案例:上位机通过串口控制LED灯开关调试要点:在XMF07A或XMF07C开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能:【1】开机后,向串口1发送“hello world!”。【2】串口1收到字节指令“0xA1”,打开LED1,发送“LED1 Open!”。【3】串口1收到字节指令“0xA2”,关闭LED1,发送“LED1 Closed!”。【4】在串口发送过程中,打开LED2作为发送数据指示灯。#define LED1_ON() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET) #define LED1_OFF() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET) #define LED2_ON() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET) #define LED2_OFF() HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET) uint8_t Tx_str1[] = "hello world!\r\n"; uint8_t Tx_str2[] = "LED1 Open!\r\n"; uint8_t Tx_str3[] = "LED1 Closed!\r\n"; uint8_t Rx_dat = 0;void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { if(Rx_dat == 0xa1) { LED1_ON(); LED2_ON(); HAL_UART_Transmit(&huart1,Tx_str2,sizeof(Tx_str2),10000); LED2_OFF(); HAL_UART_Receive_IT(&huart1,&Rx_dat,1); } else if(Rx_dat == 0xa2) { LED1_OFF(); LED2_ON(); HAL_UART_Transmit(&huart1,Tx_str3,sizeof(Tx_str3),10000); LED2_OFF(); HAL_UART_Receive_IT(&huart1,&Rx_dat,1); } } }//在mian()函数中添加以下代码: LED2_ON(); HAL_UART_Transmit(&huart1,Tx_str1,sizeof(Tx_str1),10000); //向上位机发送“hello world!” LED2_OFF(); HAL_UART_Receive_IT(&huart1,&Rx_dat,1); //启动串口1接收上位机1个字节
2022年01月21日
846 阅读
2 评论
18 点赞
【4】基于STM32CubeMX-STM32定时器开发
目录定时器的基本概述通过滴漏和漏沙瓶这两个例子简单讲述定时器的基本工作原理。STM32的常见的定时器资源: 系统嘀嗒定时器SysTick、看门狗定时器WatchDog、实时时钟RTC、基本定时器、通用定时器、高级定时器。系统嘀嗒定时器SysTick :这是一个集成在Cortex M3内核当中的定时器,它并不属于芯片厂商的外设,也就是说使用ARM内核的不同厂商,都拥有基本结构相同的系统定时器。主要目的是给RTOS提供时钟节拍做时间基准。基本定时器:TIM6、TIM7。通用定时器:TIM2、TIM3、TIM4、TIM5。在基本定时器的基础上,实现输出比较、输入捕获、PWM生成、单脉冲模式输出等功能。这类定时器最具代表性,使用也最广泛。高级定时器:TIM1、TIM8。STM32通用定时器的重要知识点通用定时器的基本结构组成:STM32的通用定时器,是一个通过可编程预分频器(Prescaler)驱动的16位自动重装主计数器(Counter Period)构成。可以对内部时钟或触发源以及外部时钟或触发源进行计数。通用定时器的基本工作原理:首先,定时器时钟信号送入16位可编程预分配器(Prescaler),该预分配器系数为0~65535之间的任意数值。预分配器溢出后,会向16位的主计数器(Counter Period)发出一个脉冲信号。预分频器,本质上是一个加法计数器,预分频系数实际上就是加计数的溢出值。定时器发生中断时间的计算方法:定时时间 = (Prescaler+1 ) X (Counter Period+1) X 1/ 定时器时钟频率时钟信号1KHz,Prescaler为9,Counter Period为999,定时时间?计算案例实训案例:外部中断信号控制LED灯开关配置要点在XMF07A或XMF07C开发板上,利用STM32CubeMX和Keil5协同开发,完成以下的功能:【1】利用TIM2实现间隔定时,每隔0.2秒将LED1的开关状态翻转。【2】利用TIM3实现间隔定时,每隔1秒将LED2的开关状态翻转。【3】修改TIM2的初始化代码,改为每隔0.5秒将LED1的开关状态翻转。/* USER CODE BEGIN 0 */ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM2) //处理TIM2间隔定时中断 { AL_GPIO_TogglePin(GPIOB,GPIO_PIN_9); } if(htim->Instance == TIM3) //处理TIM3间隔定时中断 { HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_8); } } /* USER CODE END 0 *//* USER CODE BEGIN 2 */ HAL_TIM_Base_Start_IT(&htim2); //启动定时器TIM2 HAL_TIM_Base_Start_IT(&htim3); //启动定时器TIM3 //有IT的代表使能时钟中断 /* USER CODE END 2 */
2022年01月19日
931 阅读
2 评论
26 点赞
1
...
3
4
5
...
10