《圈圈教你玩USB》 第二章 USB 硬件系统设计_测试程序的编写和调试——看书笔记
2.11 测试程序的编写和调试
2.11.4 按键驱动的编写
key.c
//定时器0初始化,用来做按键扫描
void InitTimer0(void)
{
TMOD&=0xF0; //定时器低4位是控制定时器0的,先置0
TMOD|=0x01; //然后将最低位置1,最终选择16位定时器模式
ET0=1; //允许定时器0中断
TR0=1; //启动定时器0
}
volatile uint8 idata KeyCurrent,KeyOld,KeyNoChangedTime;
volatile uint8 idata KeyPress;
volatile uint8 idata KeyDown,KeyUp,KeyLast;
volatile uint8 KeyCanChange;
//函数功能:键盘初始化
void InitKeyboard(void)
{
KeyIO=0xFF; //键盘对应的口设置为输入状态
KeyPress=0; //无按键按下
KeyNoChangedTime=0;
KeyOld=0;
KeyCurrent=0;
KeyLast=0;
KeyDown=0;
KeyUp=0;
InitTimer0(); //初始化定时器
KeyCanChange=1; //允许键值改变
}
KeyPress、KeyDown、KeyUp、KeyCanChange是提供给应用程序使用的变量。
KeyPress表示当前被按住不放的键;
KeyDown表示新按下的键;
KeyUp表示心松开的键;
//函数功能:定时器0中断处理。
//22.1184M晶体约5ms中断一次。
void Timer0Isr(void) interrupt 1
{
//定时器0重装,定时间隔为5ms,加15是为了修正重装所花费时间
//这个值可以通过软件仿真来确定,在这里设置断点,调整使两次运行
//时间差刚好为5ms即可。
TH0=(65536-Fclk/1000/12*5+15)/256;
TL0=(65536-Fclk/1000/12*5+15)%256;
if(!KeyCanChange)return; //如果正在处理按键,则不再扫描键盘
//开始键盘扫描
//保存按键状态到当前按键情况
//KeyCurrent总共有8个bit
//当某个开关按下时,对应的bit为1
KeyCurrent=GetKeyValue(); //读取键值,GetKeyValue()其实是个宏,不是函数,
//这里故意写成函数的样子,美观。它的定义在
//key.h文件中
if(KeyCurrent!=KeyOld) //如果两次值不等,说明按键情况发生了改变
{
KeyNoChangedTime=0; //键盘按下时间为0
KeyOld=KeyCurrent; //保存当前按键情况
return; //返回
}
else
{
KeyNoChangedTime++; //按下时间累计
if(KeyNoChangedTime>=1) //如果按下时间足够
{
KeyNoChangedTime=1;
KeyPress=KeyOld; //保存按键
KeyDown|=(~KeyLast)&(KeyPress); //求出新按下的键
KeyUp|=KeyLast&(~KeyPress); //求出新释放的键
KeyLast=KeyPress; //保存当前按键情况
}
}
}
2.11.5 串口驱动的编写
1. 串口驱动的重要性:
2. usart.c
//函数功能:串口初始化
void InitUART(void)
{
EA=0; //暂时关闭中断
TMOD&=0x0F; //定时器1模式控制在高4位
TMOD|=0x20; //定时器1工作在模式2,自动重装模式
SCON=0x50; //串口工作在模式1
TH1=256-Fclk/(BitRate*12*16); //计算定时器重装值
TL1=256-Fclk/(BitRate*12*16);
PCON|=0x80; //串口波特率加倍
ES=1; //串行中断允许
TR1=1; //启动定时器1
REN=1; //允许接收
EA=1; //允许中断
}
volatile uint8 Sending;
//函数功能:串口中断处理。
void UartISR(void) interrupt 4
{
if(RI) //收到数据
{
RI=0; //清中断请求,因为这里只发送,不接受,故此处只要清除中断标志即可
}
else //发送完一字节数据
{
TI=0;
Sending=0; //清正在发送标志
}
}
//函数功能:往串口发送一字节数据。
//入口参数:d: 要发送的字节数据。
void UartPutChar(uint8 d)
{
SBUF=d; //将数据写入到串口缓冲
Sending=1; //设置发送标志
while(Sending); //等待发送完毕
}
//函数功能:发送一个字符串。
//入口参数:pd:要发送的字符串指针。
void Prints(uint8 * pd)
{
while((*pd)!='\0') //发送字符串,直到遇到0才结束
{
UartPutChar(*pd); //发送一个字符
pd++; //移动到下一个字符
}
}
code uint8 HexTable[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
//函数功能:将短整数按十六进制发送。
//入口参数:待发送的整数。
void PrintShortIntHex(uint16 x)
{
uint8 i;
uint8 display_buffer[7];
display_buffer[6]=0;
display_buffer[0]='0';
display_buffer[1]='x';
for(i=5;i>=2;i--) //将整数转换为4个字节的HEX值
{
display_buffer[i]=HexTable[(x&0xf)];
x>>=4;
}
Prints(display_buffer);
}
2.11.6 PDIUSBD12读写函数和读ID的实现
1. 读D12的ID号的目的
2. PDIUSBD12的读写时序图
3. PDIUSBD12.c
//函数功能:D12写命令。
//入口参数:Command:一字节命令。
void D12WriteCommand(uint8 Command)
{
D12SetCommandAddr(); //设置为命令地址
D12ClrWr(); //WR置低
D12SetPortOut(); //将数据口设置为输出状态(注意这里为空宏,移植时可能有用)
D12SetData(Command); //输出命令到数据口上
D12SetWr(); //WR置高
D12SetPortIn(); //将数据口设置为输入状态,以备后面输入使用
}
//函数功能:读一字节D12数据。
//返 回:读回的一字节。
uint8 D12ReadByte(void)
{
uint8 temp;
D12SetDataAddr(); //设置为数据地址
D12ClrRd(); //RD置低
temp=D12GetData(); //读回数据
D12SetRd(); //RD置高
return temp; //返回读到数据
}
//函数功能:读D12的ID。
//返 回:D12的ID。
uint16 D12ReadID(void)
{
uint16 id;
D12WriteCommand(Read_ID); //写读ID命令
id=D12ReadByte(); //读回ID号低字节
id|=((uint16)D12ReadByte())<<8; //读回ID号高字节
return id;
}
4. 修改main函数
main.c
/********************************************************************
函数功能:主函数。
入口参数:无。
返 回:无。
备 注:无。
********************************************************************/
void main(void) //主函数
{
uint8 i;
uint16 id;
EA=1; //打开中断
InitKeyboard(); //初始化按键
InitUART(); //初始化串口
for(i=0;i<16;i++) //显示信息
{
Prints(HeadTable[i]);
}
id=D12ReadID();
Prints("Your D12 chip\'s ID is: ");
PrintShortIntHex(id);
if(id==0x1012)
{
Prints(". ID is correct! Congratulations!\r\n\r\n");
}
else
{
Prints(". ID is incorrect! What a pity!\r\n\r\n");
}
while(1) //死循环
{
LEDs=~KeyPress; //将按键结果取反后控制LED
if(KeyDown) //有键按下
{ //处理按下的键
if(KeyDown&KEY1)
{
Prints("KEY1 down\r\n");
KeyDown&=~KEY1;
}
if(KeyDown&KEY2)
{
Prints("KEY2 down\r\n");
KeyDown&=~KEY2;
}
if(KeyDown&KEY3)
{
Prints("KEY3 down\r\n");
KeyDown&=~KEY3;
}
if(KeyDown&KEY4)
{
Prints("KEY4 down\r\n");
KeyDown&=~KEY4;
}
if(KeyDown&KEY5)
{
Prints("KEY5 down\r\n");
KeyDown&=~KEY5;
}
if(KeyDown&KEY6)
{
Prints("KEY6 down\r\n");
KeyDown&=~KEY6;
}
if(KeyDown&KEY7)
{
Prints("KEY7 down\r\n");
KeyDown&=~KEY7;
}
if(KeyDown&KEY8)
{
Prints("KEY8 down\r\n");
KeyDown&=~KEY8;
}
}
if(KeyUp)//有键释放
{//处理释放的键
if(KeyUp&KEY1)
{
Prints("KEY1 up\r\n");
KeyUp&=~KEY1;
}
if(KeyUp&KEY2)
{
Prints("KEY2 up\r\n");
KeyUp&=~KEY2;
}
if(KeyUp&KEY3)
{
Prints("KEY3 up\r\n");
KeyUp&=~KEY3;
}
if(KeyUp&KEY4)
{
Prints("KEY4 up\r\n");
KeyUp&=~KEY4;
}
if(KeyUp&KEY5)
{
Prints("KEY5 up\r\n");
KeyUp&=~KEY5;
}
if(KeyUp&KEY6)
{
Prints("KEY6 up\r\n");
KeyUp&=~KEY6;
}
if(KeyUp&KEY7)
{
Prints("KEY7 up\r\n");
KeyUp&=~KEY7;
}
if(KeyUp&KEY8)
{
Prints("KEY8 up\r\n");
KeyUp&=~KEY8;
}
}
}
}
如果一切正确,在串口调试助手上(波特率9600 数据位8 停止位1 无硬件流控制)将会显示如下所示信息。
其中日期和时间可能不一样,这取决于当前的编译时间。
2.12 本章小结
《圈圈教你玩USB》 第二章 USB 硬件系统设计_测试程序的编写和调试——看书笔记相关推荐
- 圈圈教你玩USB学习总结
前言 最近想学习一下USB的相关知识,然后看大家都比较推荐<圈圈教你玩USB>这本书作为入门资料,看了一个礼拜看到了USB键盘实现章节.因为USB的内容比较多也比较复杂,特写下此文进行梳理 ...
- Cyclone V SoC FPGA学习之路第二章:硬件篇
Cyclone V SoC FPGA学习之路第二章:硬件篇(内部资源) 前言 上一章了解了<cycloneV device datasheet>,其中数据手册里重点介绍了电源要求,时序参数 ...
- 第二章 操作系统的硬件环境
第二章 操作系统的硬件环境 操作系统运行的硬件环境组成 中央处理器 存储系统 中断系统 I/O系统 时钟以及时钟序列 //- Linux中断处理 操作系统的运行环境主要包括系统的硬件环境和由其他的系统 ...
- 微信小程序零基础入门_第二章 小程序框架_逻辑层
第二章 小程序框架_逻辑层 2.1 逻辑层 小程序开发框架的逻辑层是基于JavaScript进行编写和实现的.在开发过程中写的所有代码,最终都被整合成一份JavaScript,在小程序启动的时候开始执 ...
- 第二章 数据的表示和运算 2.1.4 奇偶校验 [计算机组成原理笔记]
第二章 数据的表示和运算 2.1.4 奇偶校验 本笔记参考书目: 计算机组成原理(第六版.立体化教材)白中英.戴志涛 2021王道计算机组成原理视频公开课 本节重点: 奇偶校验的方法/原理 码距和检/ ...
- 慕课嵌入式开发及应用(第二章.嵌入式硬件构件与底层驱动构件基本规范)
慕课苏州大学.嵌入式开发及应用.第二章.入门与软件框架.嵌入式硬件构件与底层驱动构件基本规范 0 目录 2 入门与软件框架 2.1 嵌入式硬件构件与底层驱动构件基本规范 2.1.1 课堂重点 2.1. ...
- C语言程序设计教程_第二章:程序设计起步_笔记整理
第二章 程序设计起步[
- 圈圈教你玩转USB第三版 光盘资料
下载官网: http://service.buaapress.com.cn/mzs/file/detail/id/2199/key/b2fec916cc9fa216abe6fc836e3f7e35
- 吴昊品游戏核心算法 Round 16 —— 吴昊教你玩口袋妖怪 第二弹 777赌博机
(此图选自口袋妖怪红宝石的某个镇的娱乐场所的赌博机) 这款777赌博机存在于日本的赌场,这里,我不想再像以前一样,通过各种百科COPY一些资料,这样没有意思.我谈谈自己当年玩POKEMON时的感受吧! ...
- 【大数据】第二章:搭建Hadoop集群(送尚硅谷大数据笔记)
尚硅谷Hadoop3.x官方文档大全免费下载. https://pan.baidu.com/share/init?surl=P5JAtWlGDKMAPWmHAAcbyA 提取码:5h60 搭建集群没什 ...
最新文章
- Tableau如何连接其他电脑上的mysql数据库
- ecdf函数_关于ecdf函数的使用问题
- html标签article,html标签中section与article 区别
- 【转】Python操作MongoDB数据库
- MySQL数据库优化技巧(二)
- 使用 Karma、Mocha、Chai 搭建支持 ES6 的测试环境
- windows常用服务命令
- 【PAT - 甲级 - 1018】Public Bike Management (带权最短路,多条最短路中加条件,DFS)
- java防止上传恶意文件_从补丁分析到在野利用:揭秘CVE20201464 Windows文件签名验证绕过漏洞疑云...
- python字符串变量s的值是python网络爬虫_【Python爬虫作业】-字符串
- 作者:张家琳(1983-),女,中国科学院计算技术研究所副研究员。
- 解决xhost:unable to open display的问题
- Android TextView设置多样式文本,跑马灯以及霓虹灯效果
- odbc删除oracle驱动,恢复ODBC驱动程序(ODBC driver)
- mssql数据库置疑修复
- tcp 抓包出现spurious retransmission
- python控制键盘鼠标库pynput基本操作
- go操作redis之go-redis,python操作redis之redis
- js ajax上传文件功能
- Linux配置nginx缓存(expires)功能
热门文章
- pivot sqlserver 条件_SqlServer行转列(PIVOT),列转行(UNPIVOT)总结
- StanfordDB class自学笔记 (九) Relational Design Theory 关系设计理论
- sqlplus中调用shell_C语言程序设计——自己编写一个简易shell程序
- FFT(不ji是干甚用的diao操作)
- python学习笔记--Django入门二 Django 的模板系统
- struts2进阶篇(3)
- 可重复读隔离级别里的可能死锁
- [LeetCode] Binary Tree Level Order Traversal
- proguard-gui 混淆代码简要笔记
- 在ashx文件中使用Session