本帖最后由 tear086 于 2010-12-15 22:56 编辑
20:14:40
在2005年俺玩LPC213x时,就推出了红杏系列的LPC213xdef.h后升级为LPC213xcfg.h
20:16:06
俺2003年在DSP中也推出了红杏级的C5402def.h后升级为c5402cfg.h/c5402cfg.c
20:17:32
俺的红杏就是要让菜农将DSP/ARM等高档的单片机普及化,书写的就像单片机一样简单,而且想错都难
20:18:05
哈哈~~~在菜农眼里没有牛人,只有苦命的人
20:18:44
这次俺决定出手M0,实际是从LPC11xx开始的
20:20:12
可是开发环境只能是他们自己做的,俺高喊了开放改革
20:20:21
不听俺的
20:21:01
无奈,俺又一次红杏出墙,推出了LPC11xxcfg.h
20:22:18
晕!他的环境就是命令行调用keil的核
20:22:49
俺在北京打电话问他,说是自己开发的
20:23:24
俺对他反汇编了,是调用keil的核
20:23:45
这种技术对俺是小菜
20:24:23
这种技术俺已用了10数年
20:25:11
等等俺上传nxp的红杏全部工程包
20:25:35
里面的就是这种命令行调用技术
20:26:42
声明,群内发布
20:27:18
TinyM0CPP1.rar
20:28:52
这个就是命令行控制台不回显调用技术
20:29:37
可以在keil内直接烧写flash而不出keil的界面
20:30:57
在nxp的M0发布后,俺感觉它的头文件lpc11xx.h几乎和菜农2005年前的框架一样,但没学彻底
20:32:05
本不想再红杏出墙了,太累,想想几千行,而且是不准错一位的,有多难
20:33:14
当看见周公的头文件后,俺晕了!
又回到了旧社会----寄存器方式
20:34:00
所以,菜农在此红杏出墙,推出了刚才包内的lpc11xxcfg.h
20:34:18
俺抽颗烟去
20:35:58
本来俺不想玩芯唐的M0
20:36:14
抽了三口
20:37:10
Mr.Wrong(44500789) 20:36:00
寄存器方式确实方便,我第一次见识到是STM32的库。
今天俺就用事实讲为什么它不可取,而红杏可取
20:38:00
对,120,有西工大二个研究所协助验证
20:39:37
本来是有在ST上红杏出墙的,可是俺当时走火入魔,搞HotComm
20:40:30
为向香水城交代,俺让自己的研究生用HotCOMM搞了个“STM32ISP”
20:40:58
俺也发布了STM32的C++裸奔
20:41:11
可是就是没时间红杏一把
20:41:38
现在都没脸见香主
20:42:10
等ST上M0吧,俺直接还债,倒塌ST未来的M0
过眼云烟(106821270) 20:42:12
STM32的C++裸奔用哪个编译器啊
20:42:27
IAR
20:43:10
这次玩芯唐的M0确实是无意的
20:43:22
无心插柳柳成荫
20:46:32
哈哈~~~俺想要一套完整的开发板都要银两,这里的代理可以作证
20:47:04
俺红杏这么多就是要证明,农民不是好欺负的
20:48:10
昨天俺说过:nxp和ti都趴下了,芯唐能蹲着就算厉害,群友可以证明
20:49:09
俺一直不宣布做芯唐M0菜鸟,因为俺知道这意味着什么
20:50:15
真的开始看芯唐的资料后(在拿到研讨会开发套件前)
20:50:52
觉得太晕!!!这是俺当菜鸟最晕的一次
20:51:10
不知大家感受如何?
20:51:30
再抽三口烟去
20:53:42
在运动中学习汇编.gif
20:54:10
这是今天讲课的图
20:54:54
在汇编中理解结构比寄存器都有点
20:55:33
大家都知道在C语言的结构体吧
20:56:18
它很庞大,在单片机人的眼里,远不如寄存器操作方便
20:58:48
首先,今天演讲的标题是《ARM不是单片机,结构为何先出墙?》
20:59:32
首先,“ARM不是单片机”,为何?
20:59:58
海_塔机监控(176254851) 20:59:20
那是。。寄存器几百个,晕
这个是一点
21:00:23
ARM不是单片机”,为何?
21:00:27
回答
21:02:13
首先ARM公司不生产单片机
21:03:11
所以,ARM的寄存器就不会有何硬件相关
21:04:18
而单片机的专业厂家指令集中就有访问具体特殊寄存器的指令
21:04:58
也就意味着ARM指令集中就不会包含特殊寄存器
21:06:36
PIC单片机就是一个例证,随着档次的提高,它的指令长度从13位开始增长
21:06:51
为何????
21:07:27
可以看到PIC的指令是变长的
21:08:04
不知指令多了,而是寄存器多了
过眼云烟(106821270) 21:07:44
是指令多了不够用吗
21:08:35
PIC低档的清一色的33/35条指令
21:08:56
听晕了否???
21:09:55
pic12c508好像就20个左右的寄存器,所以指令长为13位。
21:10:51
那么档次高后,寄存器多了,13位就不够了,就变成了14位、15/。。。
21:11:23
指令集条数没变
21:12:01
ARM不是单片机”,对否?
21:12:17
抽三口去
21:14:08
不讲结构,那是教授的作为
过眼云烟(106821270) 21:14:02
外设是各家自己加的
过眼云烟(106821270) 21:14:11
然后重映射
21:14:22
对
21:15:55
因为ARM指令集内不包含特殊寄存器,而且特殊寄存器都是统一编址在2G即32位的空间内
21:17:00
这就意味着一条指令(32/16位长)不可能容纳32位的特殊寄存器地址或数据
21:18:23
所以,ARM访问特殊寄存器必须通过寄存器间接寻址得到32位的地址值
21:19:36
由于指令长度和编码长度的问题,0x00000000不可能访问到0xffffffff的位置
21:20:46
所以必须在程序的附近即上下偏移处藏匿这些需要的地址或数据
21:21:13
俺记得好像是上下2K还是4K
21:21:46
当超越了这个范围就不能访问到了
21:22:25
这就是所谓的“文字池”,即存放数据或地址的地方
21:24:24
单片机访问寄存器绝对是指向了同一位置,而ARM必须先从能访问到的“池子”里取出要访问的地址值,再得到特殊寄存器的值
21:24:58
继续讲解为何结构要出墙
21:26:17
只要明白了,真谛自然找到,也可抢在菜农前面红杏出墙~~~
21:26:50
俺抽三口烟,大家讨论
21:31:00
前些天有人说俺dsp5402红墙的好,想把5509做成红杏,问俺侵犯红杏专利否,俺说晕,随便
21:31:48
今天课要是讲完了,俺看红杏专利就不是俺的了~~~
21:32:35
为什么寄存器方式在ARM上不太合理???
21:34:00
寄存器方式首先太晕,太多,太乱
21:34:27
例如I2C
21:36:43
结构体将它们都封装在其结构体中,每个寄存器都是结构成员
21:36:55
晕,断线了
21:37:54
单片机特殊寄存器最重要的是“位”,这是我们操作的重点之重点
21:38:48
所以,红杏系列和它们都不一样在于可以控制到所有的“位”
21:39:30
但是可以告诉大家,ARM就不可能直接控制到“位”
21:40:12
M051都研究过了吧
21:41:12
ARM的“位”实际是靠C语言结构体的“位域”实现的,实际是骗人的~~~
21:41:39
依心爱婷(122607939) 21:41:06
像STM32,有块BITAND的区域,操作起来很快
21:42:05
俺给大家用硬件描述,就会理解的
21:43:04
I2Cs.CON.Bits.STA = 0;//此位必须清除,否则读不出数据
I2Cs.CON.Regs |= (1 << I2C_CON_SI) | (1 << I2C_CON_AA);
21:43:11
切记
红杏的风格是:(保留原厂定义)
->原厂的结构指针
x->菜农的结构指针
s.菜农的结构
21:45:33
Bits后是位域访问,右值为“位”
21:46:11
Regs说明右值是32位值
21:46:38
这样很方便,维护方便
21:48:15
大家知道74hc573吧
21:48:52
依心爱婷(122607939) 21:47:57
有啥,这是STM32的位操作
依心爱婷(122607939) 21:48:02
方便
可以下课了
21:48:56
俺晕
21:50:42
抽三口
21:53:34
假若用8个片选信号访问8个位呢?
21:53:57
芯唐的快速GPIO就是这样做的
21:55:06
普通GPIO就如同片选信号加位控,而快速GPIO宁可浪费空间也要换取速度
21:55:27
硬件是没有区别的
21:56:12
//DrvGPIO_SetBit()传递参数(E_PORT3, E_PIN6):(总共13条指令28个字节)
//0x00000CB4~0x00000CBB 3条指令8个字节
//0x00000420~0x00000433 10条指令20个字节
DrvGPIO_SetBit(E_PORT3, E_PIN6);
__NOP();
//DrvGPIO_ClrBit()传递参数(E_PORT3, E_PIN6):(总共15条指令32个字节)
//0x00000CBE~0x00000CC5 3条指令8个字节
//0x00000408~0x00000419 12条指令24个字节
DrvGPIO_ClrBit(E_PORT3, E_PIN6);
__NOP();
//0x00000CC8~0x00000CCD 3条指令6个字节(推荐语句)
PBitx(E_PORT3, E_PIN6)->Regs = 0;
__NOP();
//0x00000CD0~0x00000CD3 2条指令4个字节(推荐语句)
PBitx(E_PORT3, E_PIN6)->Regs = 1;
__NOP();
//0x00000CD6~0x00000CDF 5条指令10个字节(不推荐语句)
PBitx(E_PORT3, E_PIN6)->Bits.DOUT = 0;
__NOP();
//0x00000CE2~0x00000CED 6条指令12个字节(不推荐语句)
PBitx(E_PORT3, E_PIN6)->Bits.DOUT = 1;
__NOP();
//DrvGPIO_ClrBit()传递参数(E_PORT3, E_PIN6):(总共15条指令32个字节)
//0x00000CF0~0x00000CF7 3条指令8个字节
//0x00000408~0x00000419 12条指令24个字节
DrvGPIO_ClrBit(E_PORT3, E_PIN6);
__NOP();
//DrvGPIO_SetBit()传递参数(E_PORT3, E_PIN6):(总共13条指令28个字节)
//0x00000CFA~0x00000D01 3条指令8个字节
//0x00000420~0x00000433 10条指令20个字节
DrvGPIO_SetBit(E_PORT3, E_PIN6);
__NOP();
//0x00000D04~0x00000D0B 3条指令6个字节(推荐语句)
PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Regs = 0;
__NOP();
//0x00000D0E~0x00000D11 2条指令4个字节(推荐语句)
PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Regs = 1;
__NOP();
//0x00000D14~0x00000D1F 6条指令12个字节(不推荐语句)
PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Bits.DOUT = 0;
__NOP();
//0x00000D22~0x00000D2E 7条指令14个字节(不推荐语句)
PORTs.PBitx[E_PORT3].Pinx[E_PIN6].Bits.DOUT = 1;
__NOP();
//0x00000D32~0x00000D35 2条指令4个字节(极力推荐语句)
PORTs.PBit3.Pin6.Regs = 0;
__NOP();
//0x00000D38~0x00000D3B 2条指令4个字节(极力推荐语句)
PORTs.PBit3.Pin6.Regs = 1;
__NOP();
*/
while(1)
{
if (SystemTick.Timer.Bits.T500mS)//0.5S到
{
//普通GPIO书写方式
//0x00000C8E~0x00000CAD 16条指令32个字节(M05x不推荐语句)
// P3s.DOUT.Bits.Pin6 ^= 1;//LED闪烁
// PORTs.P3.DOUT.Bits.Pin6 ^= 1;//LED闪烁
PORTs.P3.DOUT.Bits.Pin6 = 1;//LED闪烁
__NOP();
PORTs.P3.DOUT.Bits.Pin6 = 0;//LED闪烁
__NOP();
//快速GPIO书写方式
//0x00000CAE~0x00000CB9 6条指令12个字节(M05x极力推荐语句)
PORTs.PBit3.Pin6.Regs ^= 1;//LED闪烁
SystemTick.Timer.Bits.T500mS = 0;
//快速GPIO书写方式
//0x00000CC6~0x00000CD1 6条指令12个字节(M05x极力推荐语句)
PORTs.PBit3.Pin6.Regs ^= 1;//LED闪烁
//普通GPIO书写方式
//0x00000CD2~0x00000CF1 16条指令32个字节(M05x不推荐语句)
P3s.DOUT.Bits.Pin6 ^= 1;//LED闪烁
21:56:32
这是俺今天做的实验
21:58:19
NUC1xxM051Seriescfg.h 发生未知错误
21:58:26
上传不了
21:58:34
新版本
21:58:47
继续
21:59:07
芯唐的FTP在俺手上
.COM 菜农弟子?<yuphone@qq.com> 21:59:10
怎么没有版本号
21:59:34
V1.11
22:00:17
以后再说
22:01:08
访问结构成员就如同我们访问文件夹,层次鲜明
22:01:45
不要认为一大串的字符效率就低
22:03:39
俺是学自动化的,程序要机器累死也不要人累,这是原则
22:04:04
所以俺的程序都是傻瓜型的
22:04:59
// __NOP();
//DrvGPIO_SetBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000D9E~0x00000DA7 4条指令10个字节
//0x00000454~0x00000463 8条指令16个字节
DrvGPIO_SetBit(E_GPB, GPB_0);
__NOP();
//0x00000DAA~0x00000DB7 7条指令14个字节
PBs.DOUT.Bits.Pin0 = 1;
__NOP();
__NOP();
//DrvGPIO_ClrBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000DBC~0x00000DC5 4条指令10个字节
//0x00000428~0x00000437 8条指令16个字节
DrvGPIO_ClrBit(E_GPB, GPB_0);
__NOP();
//0x00000DC8~0x00000DD3 7条指令14个字节
PBs.DOUT.Bits.Pin0 = 0;
__NOP();
//0x00000DD6~0x00000DE1 6条指令12个字节
PBs.DOUT.Regs |= (1 << Pin0);
__NOP();
//0x00000DE4~0x00000DEC 5条指令10个字节
PBs.DOUT.Regs &= ~(1 << Pin0);
__NOP();
__NOP();
//0x00000DF2~0x00000DFD 6条指令12个字节
PBs.DOUT.Bits.Pin0 = 1;
__NOP();
//0x00000E00~0x00000E09 5条指令10个字节
PBs.DOUT.Bits.Pin0 = 0;
__NOP();
//DrvGPIO_SetBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000E0C~0x00000E15 4条指令10个字节
//0x00000454~0x00000463 8条指令16个字节
DrvGPIO_SetBit(E_GPB, GPB_0);
__NOP();
//DrvGPIO_ClrBit()传递参数(E_GPB, GPB_0):(12条指令总共26个字节)
//0x00000E18~0x00000E21 4条指令10个字节
//0x00000428~0x00000437 8条指令16个字节
DrvGPIO_ClrBit(E_GPB, GPB_0);
__NOP();
//0x00000E24~0x00000E41 15条指令30个字节(不推荐语句)
Px(E_GPB)->DOUT.Bits.Pin0 = 1;
__NOP();
//0x00000E44~0x00000E59 11条指令22个字节(不推荐语句)
Px(E_GPB)->DOUT.Bits.Pin0 = 0;
__NOP();
//0x00000E5C~0x00000E6D 9条指令18个字节(不推荐语句)
PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 1;
__NOP();
//0x00000E70~0x00000E79 5条指令10个字节(不推荐语句)
PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 0;
__NOP();
//DrvGPIO_ClrBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000E7C~0x00000E85 4条指令10个字节
//0x00000428~0x00000437 8条指令16个字节
DrvGPIO_ClrBit(E_GPB, GPB_0);
__NOP();
//0x00000E88~0x00000E99 9条指令18个字节(推荐语句)
PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 1;
__NOP();
//0x00000E9C~0x00000EA5 5条指令10个字节(推荐语句)
PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 0;
__NOP();
//DrvGPIO_SetBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000E0C~0x00000E15 4条指令10个字节
//0x00000454~0x00000463 8条指令16个字节
DrvGPIO_SetBit(E_GPB, GPB_0);
__NOP();
//0x00000EB4~0x00000EC2 8条指令16个字节(推荐语句)
PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 0;
__NOP();
//0x00000EC6~0x00000ED0 6条指令12个字节(推荐语句)
PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 1;
__NOP();
//DrvGPIO_SetBit()传递参数(E_GPB, GPB_0):(总共12条指令26个字节)
//0x00000ED4~0x00000EDD 4条指令10个字节
//0x00000454~0x00000463 8条指令16个字节
DrvGPIO_SetBit(E_GPB, GPB_0);
__NOP();
//0x00000EE0~0x00000EEF 8条指令16个字节(推荐语句)
PORTs.PB.DOUT.Bits.Pin0 = 0;
__NOP();
//0x00000EF2~0x00000EFD 6条指令12个字节(推荐语句)
PORTs.PB.DOUT.Bits.Pin0 = 1;
__NOP();
22:05:21
PORTs.Px[E_GPB].DOUT.Bits.Pin0 = 0;
长否?
22:05:45
PORTs.PxB.DOUT.Bits.Pin0 = 0;
.COM 菜农弟子?<yuphone@qq.com> 22:05:47
不长 mdk是否可以自动识别结构体成员
22:06:28
实际在编译时是会直接找到的
22:06:56
CSS可以,如同VC助手那样
22:07:19
keil的编译太落后
22:08:11
实际敲"."时,应该成员自动显示,这样红杏菜农真的做到想错都难于上青天
22:08:11
实际敲"."时,应该成员自动显示,这样红杏菜农真的做到想错都难于上青天
22:08:38
爽
过眼云烟(106821270助手啊
22:09:13
只要敲I2Cs.后再不用写一个字了
22:09:27
没有
22:09:56
入正题
李冬发(632653918) 22:10:07
老周的界面是自己写的
22:10:14
是的
22:10:35
界面没有技术含量
李冬发(632653918) 22:10:42
不能这样说呢
22:10:52
哈哈~~~相对的
22:11:49
而且Regs也可以
22:12:48
PORTs.PB.DOUT.Bits.Pin0 = 0;
22:13:29
typedef struct {
union {
__IO NU_GPIO_T Px[5];//GPIOs.Px[0].DOUT.Regs |= 1;GPIOs.Px[0].DOUT.Bits.Pin0 = 1;
struct {
#ifdef __NUC1xx_H__//NUC1xx
__IO NU_GPIO_T PA;//GPIOs.PA.DOUT.Regs |=1;GPIOs.PA.DOUT.Bits.Pin0=1;
__IO NU_GPIO_T PB;//GPIOs.PB.DOUT.Regs |=2;GPIOs.PB.DOUT.Bits.Pin1=1;
__IO NU_GPIO_T PC;//GPIOs.PC.DOUT.Regs |=4;GPIOs.PC.DOUT.Bits.Pin2=1;
__IO NU_GPIO_T PD;//GPIOs.PD.DOUT.Regs |=8;GPIOs.PD.DOUT.Bits.Pin3=1;
__IO NU_GPIO_T PE;//GPIOs.PE.DOUT.Regs |=16;GPIOs.PE.DOUT.Bits.Pin4=1;
#else//M05x
__IO NU_GPIO_T P0;//GPIOs.P0.DOUT.Regs |=1;GPIOs.P0.DOUT.Bits.Pin0=1;
__IO NU_GPIO_T P1;//GPIOs.P1.DOUT.Regs |=2;GPIOs.P1.DOUT.Bits.Pin1=1;
__IO NU_GPIO_T P2;//GPIOs.P2.DOUT.Regs |=4;GPIOs.P2.DOUT.Bits.Pin2=1;
__IO NU_GPIO_T P3;//GPIOs.P3.DOUT.Regs |=8;GPIOs.P3.DOUT.Bits.Pin3=1;
__IO NU_GPIO_T P4;//GPIOs.P4.DOUT.Regs |=16;GPIOs.P4.DOUT.Bits.Pin4=1;
#endif
};
};
__I NU_REG RESERVED1[16];
__IO NU_GPIO_DBNCECON_T DBNCECON;//
#ifndef __NUC1xx_H__//M05x
__I NU_REG RESERVED2[31];
union {
__IO NU_GPIO_BIT_DOUT_Pins PBitx[5];//P0~P4
struct {
__IO NU_GPIO_BIT_DOUT_Pins PBit0;
__IO NU_GPIO_BIT_DOUT_Pins PBit1;
__IO NU_GPIO_BIT_DOUT_Pins PBit2;
__IO NU_GPIO_BIT_DOUT_Pins PBit3;
__IO NU_GPIO_BIT_DOUT_Pins PBit4;
};
};
#endif
}NUS_GPIO, *NUPS_GPIO;
#ifdef __NUC1xx_H__
#define NU_BASE_GPIO ((NUPS_GPIO) GPIOA_BASE)//定义硬件结构指针(硬件地址)
#define GPIOs (*NU_BASE_GPIO)//定位全局结构变量GPIOs
#define PORTs (*NU_BASE_GPIO)//定位全局结构变量PORTs
#else
#define NU_BASE_GPIO ((NUPS_GPIO) PORT0_BASE)//定义硬件结构指针(硬件地址)
#define GPIOs (*NU_BASE_GPIO)//定位全局结构变量GPIOs
#define PORTs (*NU_BASE_GPIO)//定位全局结构变量PORTs
#endif
//-------------------------------------------------------------------------------------//
22:14:00
这就是真谛的所在
22:14:58
PORTs是将5个GPIOs包罗在一体
22:15:57
这样书写随长,但“文字池”只需存PORTs一个结构地址
22:16:32
即结构里面套结构
22:17:29
目的是减少“文字池”记录结构地址的个数
而结构内的全是其偏移了 |