wuzhengmin
发表于 6 天前
// ----------------------- p10端口闪烁 -----------------------
if( P10_STATE == 0 )
LED40_SetBit(1,0);
else
LED40_ClrBit(1,0);
P10_STATE = !P10_STATE;
}
闪烁就是在高低电平切换,最容易实现的
wuzhengmin
发表于 6 天前
再来看我们下面虚拟的数码管:
wuzhengmin
发表于 6 天前
任务2:左边数码管显示P32按下次数
右边数码管显示P33按下次数
这个要学会按键按下次数的计算......
其实还是用常整数可能会比字符串更方便
u32 KEY_Count = 0;
// 任务2:左边数码管显示P32按下次数, 右边数码管显示P33按下次数void TASK_2( void ){ KEY_Count = KEY1_COUNT *10000 + KEY2_COUNT; SEG7_ShowLong( KEY_Count ,10); }
这个不好理解,有压缩饼干的味道..........
当然,要从这里入手:
u16 KEY1_COUNT = 0; //P32按钮计数
u16 KEY2_COUNT = 0; //P33按钮计数
void KEY_Task(void)
{
// ------------P32按钮计数------------
if( P32 == 0 )
{
Key_Vol++;
if( Key_Vol==5 )
{
KEY1_COUNT++;
}
}
else
{
Key_Vol = 0;
}
// ------------P33按钮计数------------
if( P33 == 0 )
{
Key_Vol_2++;
if( Key_Vol_2==5 )
{
KEY2_COUNT++;
}
}
else
{
Key_Vol_2 = 0;
}
}
wuzhengmin
发表于 5 天前
又遇到一个奇诡的问题:
下载的时候,ISP打开编译好的 .HEX文件的时候,说文件大学超出范围:
wuzhengmin
发表于 5 天前
还有个小问题:
这里原来是乘以10000
void TASK_2( void )
{
KEY_Count = KEY1_COUNT *10000 + KEY2_COUNT;//2个次数整合为1个方便显示
SEG7_ShowLong( KEY_Count ,10);
}
实验后,发现改成1000,效果更好:
void TASK_2( void )
{
KEY_Count = KEY1_COUNT *1000 + KEY2_COUNT;//2个次数整合为1个方便显示
SEG7_ShowLong( KEY_Count ,10);
}
可以解决P32按10次后乱码的问题,当然也不是彻底解决......
wuzhengmin
发表于 5 天前
u16 KEY1_COUNT = 0; //P32按钮计数
u16 KEY2_COUNT = 0; //P33按钮计数
本来2个按键起码按65534次才出问题,但是实际上按了20多次就胡乱显示啦
P33就问题不大,主要是在P32上:
确实是65535溢出问题!
//signed long KEY_Count = 0;
//float KEY_Count = 0;
u32 KEY_Count = 0;
// 任务2:左边数码管显示P32按下次数, 右边数码管显示P33按下次数
void TASK_2( void )
{
KEY_Count = KEY1_COUNT *1000 + KEY2_COUNT;//2个次数整合为1个方便显示
//printf("按键按下次数\xfd:%d 次 \r\n",(signed long)KEY_Count);
SEG7_ShowLong( KEY_Count ,10);
//SEG7_ShowFloat(KEY_Count);
}
我直觉问题是在显示上,本来想看看printf("按键按下次数\xfd:%d 次 \r\n",(signed long)KEY_Count);
KEY_Count超过65534之后是多大?
但是 USB-CDC串口不知道从ai8051u哪里发出的打印指令一直在回打:
只能先放一下,暂时*1000 ,这样P33可以按999次,P32最大按64次!
wuzhengmin
发表于 5 天前
当然,我发现还有
int SEG7_ShowString(const char *fmt, ...); 函数
去手册看看?
手册指引我们去:
上面调试仿真接口函数的详细帮助信息请参考下载软件中的“接口协议及帮助”
功能2:在数码管上显示4字节长整型数
命令格式:37H 53H 45H 47H 4CH x1 x2 00H d1 d2 d3 d4
命令说明:
第1~4字节:命令头
第5字节:功能选择(4CH显示长整型数)
第6字节:数据存储格式(0:LE, 1:BE)
第7字节:显示进制(02H:二进制, 0AH:十进制, 10H:十六进制)
第8字节:保留
第9~12字节:长整型数的存储数据
示例1:发送37H 53H 45H 47H 4CH 00H 10H 00H 12H 34H 56H 78H
在数码管上会显示78564312
示例2:发送37H 53H 45H 47H 4CH 01H 10H 00H 12H 34H 56H 78H
在数码管上会显示12345678
库函数声明:void SEG7_ShowLong(long n, char radix);//n:长整型数 radix:进制
库函数调用:SEG7_ShowLong(0x98765432, 16);
注:当超出显示范围时自动转为科学计数法进行显示
本来应该是对的,4字节长整型是可以正常显示的。但是:
//signed long KEY_Count = 0;
//float KEY_Count = 0;
//u32 KEY_Count = 0;
long KEY_Count = 0;
// 任务2:左边数码管显示P32按下次数, 右边数码管显示P33按下次数
void TASK_2( void )
{
KEY_Count = KEY1_COUNT *100 + KEY2_COUNT;//2个次数整合为1个方便显示
//printf("按键按下次数\xfd:%d 次 \r\n",(signed long)KEY_Count);
SEG7_ShowLong((long) KEY_Count ,10);
//SEG7_ShowFloat(KEY_Count);
}
4字节长整型如何正确定义?u32不行么unsigned long KEY_Count = 0; u32 KEY_Count = 0;
应该都没问题啊?反正一超出65534就乱了,根源应该是计数器溢出中断?
65536代表的是一个16位计数器的最大值。这个计数器由高8位(TH0)和低8位(TL0)组成,可以存储2^16=65536个数。当计数器从65536开始计数时,经过一段时间后会溢出并产生中断。
所以根本问题不是显示!
我们验证一下:
//signed long KEY_Count = 0;
//float KEY_Count = 0;
//u32 KEY_Count = 0;
unsigned long KEY_Count = 0;
// 任务2:左边数码管显示P32按下次数, 右边数码管显示P33按下次数
void TASK_2( void )
{
KEY_Count = KEY1_COUNT *100 + KEY2_COUNT;//2个次数整合为1个方便显示
//printf("按键按下次数\xfd:%d 次 \r\n",(signed long)KEY_Count);
KEY_Count = 88888888;
SEG7_ShowLong((long) KEY_Count ,10);
//SEG7_ShowFloat(KEY_Count);
}
wuzhengmin
发表于 5 天前
当然,实际上65535也是够用的
我们乘以100
这是P32可以按655次,P33反正可以进位,就算不进位也有99次,混过去是可以的...........
wuzhengmin
发表于 5 天前
最后就是拟键盘!
任务3:按下数字按键在数码管显示对应的按键数字!
例:按下按键0数码管显示0;
先学会用extern 关键字:
extern u32 REC_NUM;//变量是在io.c建立的
//这个变量要在其他函数使用,就要加extern
//关键字,并且这里不能赋值,就是不能这样:
//extern u32 REC_NUM=0;只能extern u32 REC_NUM;
//意思是我已经在别的地方定义好了。加了extern
//编译器就会自动去别的地方找到这个变量
看看主函数:
void main(void)
{
Sys_init(); //系统初始化
usb_init(); //USB CDC 接口配置
IE2 |= 0x80; //使能USB中断
Timer0_Init(); //定时器初始化
EA = 1; //IE |= 0X80;
P40 = 0;
while (DeviceState != DEVSTATE_CONFIGURED); //等待USB完成配置
while(1)
{
if (bUsbOutReady) //如果接收到了数据
{
REC_NUM = UsbOutBuffer-48;
//我们接受的数据在UsbOutBuffer里面
/*功能:在虚拟键盘上按键然后发送相应的键值到设备
命令格式:4EHH 59H 50H 00H x1 00H 00H
命令说明:
?
第1~4字节:命令头
第5字节:保留
第6字节:按键键值
第7~8字节:保留
我们需要第6个字节(从0数是第5个)
UsbOutBuffer-48;-48就是ASCII编码问题,我们
要直接显示数字,不需要显示ASCII编码
上位机发0的编码48过来,我们直接发0回去显示
用void TASK_3( void )完成任务
示例:接收到4BH 45H 59H 50H 00H 30H 00H 00H
表示数字键0被按下*/
// USB_SendData(UsbOutBuffer,OutNumber); //发送数据缓冲区,长度(接收数据原样返回, 用于测试)
usb_OUT_done(); //
}
Task_Pro_Handler_Callback(); //执行功能函数
}
}
u32 REC_NUM是在io.c里定义赋初值的,顺便写好任务3函数void TASK_3( void )
u32 REC_NUM = 0;
// 任务3:按下数字按键在数码管显示对应的按键数字!
void TASK_3( void )
{
SEG7_ShowLong( REC_NUM ,10);
}
wuzhengmin
发表于 5 天前
课后练习,好像很难
不过,我们已经学完了十集,还算可以啦,没有间断,一鼓作气就算合格
今天到此为止啦
页:
5
6
7
8
9
10
11
12
13
14
[15]
16
17