0%

前言

本文主要内容在于对Arduino Nano的定时器0的探索,注意到Arduino Nano的芯片型号为ATmega328p,而网上并没有这方面的数据手册翻译
所以本人将这部分内容进行一定的翻译并进行一定程度的解释

手册正文

TIMER0概述

ATmega328p芯片共有三个定时器,分别为TIMER0,TIMER1,TIMER2,要注意TIMER0作为一个8位定时器,许多delay函数都依赖它
TIMER0除了常规的定时中断功能外,还可操纵引脚输出PWM信号,查阅数据手册得知,TIMER0可操控的引脚为Pin6(OC0A)和Pin5(OC0B)

8-bit Timer/Counter0 with PWM

功能特性

- 两个独立的输出比较单元
- 双缓冲区的输出比较寄存器
- 当值匹配时自动清空计时器(自动重装载)
- 排除小错误,自动修正相位的PWM输出
- 可变的PWM周期
- 频率发生器
- 三个独立的中断源(TOV0,OCF0A,OCF0B)

概述

TIMER0是一个通用的八位计时器,拥有两个独立的输出比较单元和PWM外设。也可用于准确的程序运行计时(事件管理)和波形生成

下图是一个八位定时器的示意图

14-1.png

PRTIM0位必须被设置为0才能启动TIMER/COUNTER0模组

约定与定义

以下给出一些约定的符号,便于之后的理解

Arduino IDE没有补全功能,写起来实在费劲
而VScode作为万能的编辑器,当然是可以支持Arduino的

插件下载

搜索下载Arduino扩展
1.png
配置插件,在settings.json中加入如下配置

1
2
"arduino.path": "{path}\\Arduino", //{path}是你的Arduino安装路径
"arduino.logLevel": "info"

自动补全&语法检查

到这里,你已经可以编辑.ino文件了,但是有一个问题,类似于digitalWrite(3,HIGH)一类的语句会有红线告诉你存在错误,看起来很烦,我们这样配置一下用户区的settings.json

1
2
3
4
5
6
7
8
9
{
"arduino.path": "{path}\\Arduino", //{path}是你的Arduino安装路径
"C_Cpp.intelliSenseEngine": "Tag Parser",
"editor.insertSpaces": true,
"files.autoGuessEncoding": true,
"arduino.logLevel": "info",
"explorer.confirmDelete": false,
"editor.detectIndentation": false,
}

这样就解决了,但是调用函数的时候还是没有补全功能,这是因为没有加入库文件造成的
在c_cpp_properties.json的includePath中加入

1
2
3
4
5
6
7
8
"includePath": [
"{path}\\Arduino\\hardware\\arduino\\avr\\cores\\arduino",
"{path}\\Arduino\\hardware\\arduino\\avr\\variants\\eightanaloginputs",
"{path}\\Arduino\\hardware\\tools\\avr\\lib\\gcc\\avr\\7.3.0\\include",
"{path}\\Arduino\\hardware\\tools\\avr\\lib\\gcc\\avr\\7.3.0\\include-fixed",
"{path}\\Arduino\\hardware\\tools\\avr\\avr\\include",
"{path}\\Arduino\\libraries"
],

上传程序

点击[Select Board Type]
选择你的开发板型号
2.png
再点击[Select Serial Port]选择使用的串口
然后Ctrl+Alt+U即可上传

中文乱码修复

上传过程中,有可能会发现控制台中出现中文乱码,修复的方法如下
打开

C:\Users\YourUserName\%.vscode%\extensions\vsciot-vscode.vscode-arduino-0.4.0\out\src\common中的util.js

找到如下代码
1
2
3
4
5
6
7
8
9
10
11
if (os.platform() === "win32") {
try {
const chcp = child_process.execSync("chcp.com");
codepage = chcp.toString().split(":").pop().trim();
}
catch (error) {
outputChannel_1.arduinoChannel.warning(`Defaulting to code page 850 because chcp.com failed.\
\rEnsure your path includes %SystemRoot%\\system32\r${error.message}`);
codepage = "850";
}
}

将其注释掉,然后重新启动编辑器,再次上传,问题解决

现在,就可以愉快的用VScode编写Arduino程序辣

编译缓慢解决方法

注意到

1
[Warning] Output path is not specified. Unable to reuse previously compiled files. Upload could be slow. See README.

只需在.vscode -> arduino.json文件中将输出目录 output 配置一下就可以大大提高二次下载的编译速度。

1
2
3
4
5
6
7
{
"configuration": "cpu=atmega328",
"board": "arduino:avr:nano",
"port": "COM5",
"output": "./build",
"sketch": "test.ino"
}

下载IDE

去官网下载Arduino IDE IDE下载

然后安装

1

测试

选中一个示例进行测试

2

选择你的设备型号,然后上传程序

你的Arduino会开始亮灯了!

题意

给定一个字符串S($ |S| \le 10^6 $)
求S中出现次数不为1的子串长度与出现次数乘积的最大值

思路

用SAM统计子串出现的次数,并记录对应的长度
然后在parent树上遍历一遍就能得出答案
实现的时候注意细节判断

代码

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
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
long long ans;
namespace SAM{
int trans[2000100][26],maxlen[2000100],sz[2000100],link[2000100],Nodecnt,last,barrel[2000100],rank[2000100];
void init(void){
Nodecnt=0;
last=0;
link[0]=-1;
maxlen[0]=0;
}
void append(int x){
int o = ++Nodecnt;
maxlen[o] = maxlen[last] + 1;
sz[o] = 1;
int p = last;
while(p!=-1 && (!trans[p][x]) ){
trans[p][x] = o;
p = link[p];
}
if(p == -1){
link[o] = 0;
last = o;
return;
}
int y = trans[p][x];
if(maxlen[p]+1 == maxlen[y]){
link[o] = y;
}
else{
int z = ++Nodecnt;
for(int j=0;j<26;j++)
trans[z][j] = trans[y][j];
maxlen[z] = maxlen[p]+1; //!
while(p!=-1 &&(trans[p][x] == y)){
trans[p][x] = z;
p = link[p];
}
link[z] = link[y];
link[y] = z;
link[o] = z;
}
last = o;
}
void CalcSz(void){
int maxsz = 0;
for(int i=1;i<=Nodecnt;i++){
barrel[maxlen[i]]++;
maxsz = max(maxsz,maxlen[i]);
}
for(int i=1;i<=maxsz;i++)
barrel[i]+=barrel[i-1];
for(int i=1;i<=Nodecnt;i++)
rank[barrel[maxlen[i]]--] = i;
for(int i=Nodecnt;i>=1;i--){
int tmp = rank[i];
sz[link[tmp]]+=sz[tmp];
}
}
void CalcAns(void){
for(int i=1;i<=Nodecnt;i++){
if(sz[i]>1){
// printf("%d %d\n",sz[i],maxlen[i]);
ans=max(ans,1LL*sz[i]*maxlen[i]);
}
}
}
};
char s[1000100];

int main(){
ans = 0;
scanf("%s",s+1);
int n=strlen(s+1);
SAM::init();
for(int i=1;i<=n;i++){
SAM::append(s[i]-'a');
}
SAM::CalcSz();
SAM::CalcAns();
printf("%lld\n",ans);
return 0;
}