目录
本篇文章主要介绍IIC通信协议,同时给大家介绍一下蓝桥杯嵌入式的模块的AT24C02和MCP4017,此外本篇博客会采用按键控制PB14来读取可编程电阻MCP分的电压值,并将电压值存储在AT24C02中。
I2C(IIC,Inter-Integrated Circuit), 一种半双工通信协议,采用两线式串行总线, 它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据,这两条线必须通过上拉电阻连接正电源。数据传输只能在总线不忙时启动。在CPU与被控IC之间、IC与IC之间进行双向传送,高速IIC总线一般可达400kbps以上。

对于STM32来说,G4系列的芯片自带3个硬件IIC,而对于我们的比赛来说,官方为我们提供的代码采用的不是硬件上的IIC,而是使用PB6 和 PB7这两个IO口来模拟IIC的进程。接下来我会结合蓝桥杯嵌入式为大家提供的参考代码来为大家讲解一下IIC通信的一些操作。
下图是IIC起始和停止时序图,起始和停止均由主机来发出,IIC总线在主机发出起始信号后处于忙碌状态,而在主机发出停止信号后,总线处于空闲状态(I2C总线总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态此时各个器件的输出级场效应管均处在截止状态,即释放总线,由两条信号线各自的上拉电阻把电平拉高)。

起始条件:在SCL保持为高电平的情况下,SDA出现一个下降沿,对应代码部分为:
void I2CStart(void)
{
SDA_Output(1);
delay1(DELAY_TIME);
SCL_Output(1);
delay1(DELAY_TIME);
SDA_Output(0);
delay1(DELAY_TIME);
SCL_Output(0);
delay1(DELAY_TIME);
}
停止条件:在SCL保持为高电平的情况下,SDA出现一个上升沿,对应代码部分为:
void I2CStop(void)
{
SCL_Output(0);
delay1(DELAY_TIME);
SDA_Output(0);
delay1(DELAY_TIME);
SCL_Output(1);
delay1(DELAY_TIME);
SDA_Output(1);
delay1(DELAY_TIME);
}
每当主机向从机发送完一个字节的数据,主机总是需要等待从机发出一个应答信号,以检验从机是否成功接收到了数据。
下面就是应答时序图,只有在DATA OUT 被置为低的时候,才会被认为是从机产生应答,否则被认为是不应答。

等待从机发送应答对应代码部分:
unsigned char I2CWaitAck(void)
{
unsigned short cErrTime = 5;
SDA_Input_Mode();
delay1(DELAY_TIME);
SCL_Output(1);
delay1(DELAY_TIME);
while(SDA_Input())
{
cErrTime--;
delay1(DELAY_TIME);
if (0 == cErrTime)
{
SDA_Output_Mode();
I2CStop();
return ERROR;
}
}
SDA_Output_Mode();
SCL_Output(0);
delay1(DELAY_TIME);
return SUCCESS;
}
主从机发送应答或者非应答对应代码:
/**
* @brief I2C发送确认信号
* @param None
* @retval None
*/
void I2CSendAck(void)
{
SDA_Output(0);
delay1(DELAY_TIME);
delay1(DELAY_TIME);
SCL_Output(1);
delay1(DELAY_TIME);
SCL_Output(0);
delay1(DELAY_TIME);
}
/**
* @brief I2C发送非确认信号
* @param None
* @retval None
*/
void I2CSendNotAck(void)
{
SDA_Output(1);
delay1(DELAY_TIME);
delay1(DELAY_TIME);
SCL_Output(1);
delay1(DELAY_TIME);
SCL_Output(0);
delay1(DELAY_TIME);
}
在介绍读写字节前,我要给大家强调一点,数据传输过程中,数据传输保持稳定(在SCL高电平期间,SDA一直保持稳定,没有跳变),只有当SCL被拉低后,SDA才能被改变在SCL为高电平期间(有效数据时间段),发送数据,发送8次数据,如果数据为1,显然SDA是被拉高;如果数据为0,那么SDA被拉低

对于IIC协议来说,传输到SDA上的数据必须是八位,在数据传输的时候,先传输数据的最高位,再传输数据的最低位,也就是嵌入式工程师所说的高位先行(MSB),每当有一个字节的数据发送后,必须发送一位应答位,总的数据就是8位数据加1位应答,也就是说一帧有9位数据。

读写操作对应的代码部分:
/**
* @brief I2C发送一个字节
* @param cSendByte 需要发送的字节
* @retval None
*/
void I2CSendByte(unsigned char cSendByte)
{
unsigned char i = 8;
while (i--)
{
SCL_Output(0);
delay1(DELAY_TIME);
SDA_Output(cSendByte & 0x80);
delay1(DELAY_TIME);
cSendByte += cSendByte;
delay1(DELAY_TIME);
SCL_Output(1);
delay1(DELAY_TIME);
}
SCL_Output(0);
delay1(DELAY_TIME);
}
/**
* @brief I2C接收一个字节
* @param None
* @retval 接收到的字节
*/
unsigned char I2CReceiveByte(void)
{
unsigned char i = 8;
unsigned char cR_Byte = 0;
SDA_Input_Mode();
while (i--)
{
cR_Byte += cR_Byte;
SCL_Output(0);
delay1(DELAY_TIME);
delay1(DELAY_TIME);
SCL_Output(1);
delay1(DELAY_TIME);
cR_Byte |= SDA_Input();
}
SCL_Output(0);
delay1(DELAY_TIME);
SDA_Output_Mode();
return cR_Byte;
}
这里我要给大家解释一点代码,SDA_Output(cSendByte & 0x80);
函数每次接收过来的都是一个字节,而通过&0x80就会保留最高位的数据,舍弃后七位的数据,也就是说,通过这个操作之后,就只有1位数据被保存了下来,然后通过cSendByte += cSendByte;将这一位数据进行加法计算,这可以看作是这一位数据的左移运算。同样的道理也适用于cR_Byte += cR_Byte;cR_Byte |= SDA_Input();这两句代码。
AT24C02是一款2K容量的串行电可擦除只读存储器,内部包含256个字节,每个字节8位。

在官方给出的原理图上,AT24C02和MCP4017被挂载在了PB6 PB7两个接口上,也就以为着,AT24C02是做为从机来跟单片机进行通信的。这就要求我们去看一下数据手册,找到其从机地址。


手册中的地址前4位是固定不变的,后3位是可以根据电平的高低来决定,最后一位由开发者决定是对其进行读操作还是写操作来决定最后一位的数据是0还是1。而开发板将A2 A1 A0全部接地,这就决定了我们如果用读操作就是0xA1,写操作就是0xA0;

字节写操作需要由单片机发出起始状态和器件地址,紧跟着给出一个8位数据地址。一经收到该地址,AT24C02就立刻发送应答,并随时钟输入8位数据。在收到8位数据之后,AT24C02再次发送应答,单片机发送停止信号来终止写操作。同时,这里要注意的是AT24C02每次写完内容后会自动指向下一个内存空间。但是这里一定要延时一下,这样才能保证写入的正确
AT24C02写操作对应代码部分:
void EEPROM_write(unsigned char address,unsigned char data)
{
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CSendByte(data);
I2CWaitAck();
I2CStop();//停止IIC
HAL_Delay(5);
}

AT24C02能进行8字节页面写入,04、08和16系列设备能进行16字节页面写入。激发写页面与激发写字节相同,只是数据传送设备无须在第一个字节随时钟输入之后,发出一个停止状态。在EEPROM确认收到第一个数据之后,数据传送设备能再传送7个(1KB、2KB)或15个(4KB、8KB、16KB)数据,每一个数据收到之后,EEPROM都将通过SDA回送一个确认信号,最后数据传送设备必须通过停止状态终止页面写序列。
页写操作对应代码部分:
void EEPROM_pagewrite(unsigned char *pageBuf,unsigned char address,unsigned char num)
{
I2CStart();
I2CSendByte(0xa0); // 器件地址
I2CWaitAck();
I2CSendByte(address); // 写数据地址
I2CWaitAck();
while(num--)
{
I2CSendByte(*pageBuf++);
I2CWaitAck();
}
I2CStop();
delay1(500);
}
读取操作分为三种,分别是当前地址读取,一个是随机读取,另一个是顺序读取。这里给大家介绍一下随机读取,随机读取的时序图如下所示。

先由主机发送一个起始信号,紧接着再发送器件地址(0xa0),等待从机响应,然后发送读取的地址,等待从机响应,之后再次发送起始信号,这时候发送的器件地址就是0xa1了,等待从机回应之后,然后才开始数据读取,每次进行数据读取后,需要进行等待响应操作,如果收到的响应是不响应,那么这时候发送停止信号,代表着读取结束。
unsigned char EEPROM_read(unsigned char address)
{
unsigned char dat;
I2CStart();
I2CSendByte(0xa0);
I2CWaitAck();
I2CSendByte(address);
I2CWaitAck();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
dat = I2CReceiveByte();
I2CWaitAck();
I2CStop();
return dat;
}
MCP4017是一款可编程的电阻,其内置了7位寄存器,共计127个档位的分辨率。在蓝桥杯嵌入式比赛中,MCP4017同样放在了PB6 PB7 两个IO上,我们可以用IIC总线来跟他通信。

对于蓝桥杯嵌入式比赛来说,采用的是MCP4017T-104ELT,也就是说他的最大电阻达到了100K。

通过这张图,我们可以清晰的看出,随着我们向MCP中输入的数越大,他对应的电阻也就越大,当我们传入0x7f时,对应的电阻就是100K。这里要注意的一点是,我们写进去的一个数字(0-127),读出来也是一个数字,转化为电阻阻值:R = 787.4 * read_resistor 欧,电压:3.3*(R/(R+10)) (假设外接的电压为3.3)

通过阅读数据手册,我们可以得到MCP4017的从机地址,如果是读操作的话就是0x5f,写操作的话就是0X5E。接下来,我们根据时序图来编写MCP的读写操作。

这个就比AT24C02好看多了,先发送起始信号,等待响应,发送数据,等待响应,结束信号,一个写操作就结束了。对应代码部分如下:
void MCP4017_write(unsigned char value)
{
I2CStart();
I2CSendByte(0x5e);
I2CWaitAck();
I2CSendByte(value);
I2CWaitAck();
I2CStop();
}

这里需要注意的一点是主设备负责发起响应和响应信号。如果出现响应信号,MCP4017将中止此传输并释放总线。
读取操作对应的代码部分:
unsigned char MCP4017_read(void)
{
unsigned char value;
I2CStart();
I2CSendByte(0x5f);
I2CWaitAck();
value = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return value;
}
写好的按键工程 提取码:2471
大家可以在我这个按键工程的基础上进行修改。
通过开发板上的B2 B3 B4个按键,来分别控制MCP4017不同的电阻值,同时利用B1来显示上一次存储到AT24C02中的电压。
1、将PB6 PB7设定为推挽输出

2、设定PB14为ADC通道,并完成相关配置



Resolution:ADC采样的分辨率这里直接默认选择12位的精度就可以了,如输入电压为0-3.3V,12位,即0V对应0,3.3V对应2^12-1=4095,通过这个转换我们就可以算出对应的电压值。
Rank:采样间隔设置我们这里选择默认2.5就行了,间隔越小采样频率越高。 之后,咱们的Cubemx的配置就算基本完成了,点击generate生成代码即可。不过要记得把官方提供的i2c_hal.c和i2c_hal.h加入我们的工程。
打开工程后,在i2c_hal.c里面添加AT24C02和MCP4017的代码,并且在.h文件中声明一下
unsigned int adc_val;
float vol;
void Get_vol()
{
HAL_ADC_Start(&hadc1);
adc_val = HAL_ADC_GetValue(&hadc1);
vol = adc_val/4096.0f * 3.3f;
}
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>© Copyright (c) 2022 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "adc.h"
#include "tim.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
#include "lcd.h"
//#include "fonts.h"
#include "interrupt.h"
#include "stdio.h"
#include "i2c_hal.h"
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
char text[20];
extern unsigned int TIM3_count;
extern struct keys key[4];
unsigned char TIM3_count_H;
unsigned char TIM3_count_L;
unsigned int EEPROM_temp;
unsigned char res_4017;
unsigned int PB14_ADC;
float volt1;
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM3_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
LCD_Init();
LCD_Clear(Blue);
LCD_SetBackColor(Blue);
LCD_SetTextColor(White);
HAL_TIM_Base_Start_IT(&htim3);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_ADC_Start(&hadc1);
PB14_ADC = HAL_ADC_GetValue(&hadc1);
volt1 = PB14_ADC * 3.5/4096;
sprintf(text,"Now time_value:%d",TIM3_count);
LCD_DisplayStringLine(Line4 ,(unsigned char *)text);
EEPROM_temp = (EEPROM_read(0x00)<<8)+EEPROM_read(0x01);
sprintf(text,"EEPROM_temp:%d",EEPROM_temp);
LCD_DisplayStringLine(Line1 ,(unsigned char *)text);
sprintf(text,"RES %5.4fK",res_4017*0.7874);
LCD_DisplayStringLine(Line6,(uint8_t *)text);
sprintf(text,"Vol %5.4fV",3.3*res_4017*0.7874/(res_4017*0.7874 + 10));
LCD_DisplayStringLine(Line3, (unsigned char *)text);
sprintf(text,"ture %5.4fV",volt1);
// sprintf(text,"ture %d",PB14_ADC);
LCD_DisplayStringLine(Line7, (unsigned char *)text);
if(key[0].single_flag == 1)
{
sprintf(text,"key0down");
LCD_DisplayStringLine(Line8,(uint8_t *)text);
MCP4017_write(0x00);
res_4017 = MCP4017_read();
key[0].single_flag = 0;
}
else if(key[1].single_flag == 1)
{
sprintf(text,"key1down");
LCD_DisplayStringLine(Line8,(uint8_t *)text);
MCP4017_write(0x0d);
res_4017 = MCP4017_read();
key[1].single_flag = 0;
}
else if(key[2].single_flag == 1)
{
sprintf(text,"key2down");
LCD_DisplayStringLine(Line8,(uint8_t *)text);
key[2].single_flag = 0;
MCP4017_write(0x40);
res_4017 = MCP4017_read();
}
else if(key[3].single_flag == 1)
{
TIM3_count_H = TIM3_count >> 8;
TIM3_count_L = TIM3_count & 0xff;
EEPROM_write(0x00,TIM3_count_H);
HAL_Delay(10); //写入需要时间,延时是为了给写操作留出时间
EEPROM_write(0x01,TIM3_count_L);
HAL_Delay(10);
sprintf(text,"key3down");
MCP4017_write(0x7f);
res_4017 = MCP4017_read();
LCD_DisplayStringLine(Line8,(uint8_t *)text);
key[3].single_flag = 0;
}
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV3;
RCC_OscInitStruct.PLL.PLLN = 20;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
/** Initializes the peripherals clocks
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC12;
PeriphClkInit.Adc12ClockSelection = RCC_ADC12CLKSOURCE_SYSCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
最终代码 提取码:2471
目录前言: 一、ASC分析代码实现二、 卡片分析代码实现三、 直线分析代码实现四、货物摆放分析代码实现小结:前言: 在刷题的过程中,发现蓝桥杯的题目和力扣的差别很大。让人有一种不一样的感觉,蓝桥杯题目偏向对于实际问题用编程去的解决,而力扣给人感觉很锻炼自己的编程思维,逻辑能力。两者结合去刷,相信会有不一样的收获。 一、ASC 已知大写字母A的ASCII码为65,请问大写字母L的ASCII码是多少?分析 这道题目看上去很简单,我们需确定自己计算的准确,所以我建议用编程去解决。代码实现publicclassTest8{publicstaticvoidmain(String[]args){Sy
LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L
?作者主页:静Yu?简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者?社区地址:前端知识交流社区?博主的个人博客:静Yu的个人博客?博主的个人笔记本:前端面试题个人笔记本只记录前端领域的面试题目,项目总结,面试技巧等等。接下来会更新蓝桥杯官方系统基础练习的VIP试题,依然包括解题思路,源代码等等。问题描述:给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是: 如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“threeo’clock”。 如果m不为0,则将时读出来,然后将分读出来,如5
十四届蓝桥青少组模拟赛Python-20221108T1.二进制位数十进制整数2在十进制中是1位数,在二进制中对应10,是2位数。十进制整数22在十进制中是2位数,在二进制中对应10110,是5位数。请问十进制整数2022在二进制中是几位数?print(len(bin(2022))-2)#运行结果:11T2.晨跑小蓝每周六、周日都晨跑,每月的1、11、21、31日也晨跑。其它时间不晨跑。已知2022年1月1日是周六,请问小蓝整个2022年晨跑多少天?#样例代码1ls=[0,31,28,31,30,31,30,31,31,30,31,30,31]ans=0k=6foriinrange(1,13)
本文代码使用HAL库。文章目录前言一、MCP4017的重要特性二、MCP4017计算RBW阻值三、MCP4017地址四、MCP4017读写函数五、CubeMX创建工程(利用ADC测量MCP4017电压)、对应代码:总结前言一、MCP4017的重要特性蓝桥杯板子上的是MCP4017T-104ELT,如图1。MCP4017是一个可编程电阻,通过写入的数值可以改变电阻的大小。重点在于6引脚(W),5引脚(B
一、概述在之前的一篇博文中,记录了AT24C01、AT24C02芯片的读写驱动,先将之前的相关文章include一下:1.IIC驱动:4位数码管显示模块TM1637芯片C语言驱动程序2.AT24C01/AT24C02读写:AT24C01/AT24C02系列EEPROM芯片单片机读写驱动程序本文记录分享AT24C04、AT24C08、AT24C16芯片的单片机C语言读写驱动程序。二、芯片对比介绍型号容量bit容量byte页数字节/页器件寻址位可寻址器件数WordAddress位数/字节数备注AT24C044k5123216A2A149/1WordAddress使用P0位AT24C088k1024
目录一、原理部分1、什么是串行通信(1)并行通信与串行通信(2)串行通信的制式(3)串行通信的主要方式 2、配置串口(1)SCON和PCON:串行口1的控制寄存器(2)SBUF:串行口数据缓冲寄存器 (3)AUXR:辅助寄存器编辑(4)ES、PS:与串行口1中断相关的寄存器(5)波特率设置 3、串口框架编写二、程序案例一、原理部分1、什么是串行通信(1)并行通信与串行通信微控制器与外部设备的数据通信,根据连线结构和传送方式的不同,可以分为两种:并行通信和串行通信。并行通信:数据的各位同时发送与接收,每个数据位使用一条导线,这种方式传输快,但是需要多条导线进行信号传输。串行通信:数据一位一
问题描述小蓝负责一个公司的考勤系统,他每天都需要根据员工刷卡的情况来确定每个员工是否到岗。当员工刷卡时,会在后台留下一条记录,包括刷卡的时间和员工编号,只要在一天中员工刷过一次卡,就认为他到岗了。现在小蓝导出了一天中所有员工的刷卡记录,请将所有到岗员工的员工编号列出。输入格式输入的第一行包含一个正整数n,表示一天中所有员工的刷卡记录的条数。接下来n行,每行包含一条刷卡记录,每条刷卡记录的格式为:HH:MM:SSID其中HH:MM:SS表示刷卡时间,HH为一个0到23之间的两位十进制整数(可能含前导0)表示时,MM为一个0到59之间的两位十进制整数(可能含前导0)表示分,SS为一个0到59之间的
目录1 例题1.1 卡片换位1.2 人物相关性分析2 字符串的读取2.1 综述2.2 scanf2.3 getline/getchar/get2.4 注意2.5 说明3 C语言中字符串有关问题3.1 常用函数3.2 使用实例3.3 附一些函数先看例题1 例题1.1 卡片换位问题描述你玩过华容道的游戏吗?这是个类似的,但更简单的游戏。看下面3x2的格子在其中放5张牌,其中A代表关羽,B代表张飞,*代表士兵。还有一个格子是空着的。你可以把一张牌移动到相邻的空格中去(对角不算相邻)。游戏的目标是:关羽和张飞交换位置,其它的牌随便在哪里都可以。输入格式:输入两行6个字符表示当前的局面输出格式:一个整
原题链接https://www.dotcpp.com/oj/problem3162.html想直接看题解的,跳转到第三次尝试即可。已AC。解析:(1)首先大家要知道什么叫互质:以及它们的性质:欧拉函数在数论中,对正整数n,欧拉函数φ(n)是小于或等于n的正整数中与n互质的数的数目。此函数以其首名研究者欧拉命名,它又称为φ函数(由高斯所命名)或是欧拉总计函数(totientfunction,由西尔维斯特所命名)。例如φ(8)=4,因为1,3,5,7均和8互质。也可以从简化剩余系的角度来解释,简化剩余系(reducedresiduesystem)也称既约剩余系或缩系,是m的完全剩余系中与m互素的数