IO口线性映射的用法
本帖最后由 zhouwenjing 于 2013-1-16 09:53 编辑第一种情况,所有的IO都在同一个寄存器上。如下图:
我使用了P0口上的1,4,7三个IO口,作为输出,用于控制三个继电器,继电器编号分别为1,2,3
P01 P04 P07
| | | |
-----------------------------------------
| MCU |
|______________________|
| | | |
P22 P25 P27 P29
如果按一般的操作,代码该是如下写:void RelayOpen(int rid)
{
if(rid==1)
{
P0|=(1<<1);
}
else if(rid==2)
{
P0|=(1<<4);
}
else if(rid==3)
{
P0|=(1<<7);
}
}但是想一想,如果要控制的IO口很多,这样写是不是过于繁琐呢!
如何简化这段代码呢?其实仔细想一想,这段代码还是很有规律的,除了IO口德编号不一样,其他的都很相似。根据这个规律,我把代码改写成如下的样子
const INT8U RELAY_IO_MAP[]={1<<1,1<<4,1<<7};
void RelayOpen(int rid)
{
if((rid<=3)&&(rid>0))
{
P0|=RELAY_IO_MAP;
}
}
这样吧IO口编号线性映射一下,代码就简化很多了,可维护性也增强了很多
第二种情况,有的IO不在同一个寄存器上。如下图:
我使用了P0口上的1,7和P2口的2和5四个IO口,作为输出,编号分别为1,2,3,4
P01 P04 P07
| | | |
-----------------------------------------
| MCU |
|______________________|
| | | |
P22 P25 P27 P29
通常我们会这样写:void RelayOpen(int rid)
{
if(rid==1)
{
P0|=(1<<1);
}
else if(rid==2)
{
P0|=(1<<7);
}
else if(rid==3)
{
P2|=(1<<2);
}
else if(rid==4)
{
P2|=(1<<5);
}
}那由如何简化这段代码呢??
后面的跟上。。。。。。。
m3能将端口的位映射到专用地址,操作时不影响其他位 这个基本上很难
而且不简化可读性更强,可移植性强些
whatcanitbe 发表于 2013-1-15 22:34 static/image/common/back.gif
这个基本上很难
而且不简化可读性更强,可移植性强些
1、第二个问题也是很容易简化的
2、普通写法是很直观,但是可移植性不见得强哦,简化后的代码,如果使用宏定义的话,基本上只需配置几个参数就OK了。 NJ8888 发表于 2013-1-15 22:20 static/image/common/back.gif
m3能将端口的位映射到专用地址,操作时不影响其他位
有吗,我怎么没有看到过呢??
能否截个图看看 const INT8U RELAY_IO_MAP[]={1<<1,1<<7,1<<2,1<<5};
void RelayOpen(int rid)
{
if((rid<3)&&(rid>0))
{
P0|=RELAY_IO_MAP;
}
else
{
P2|=RELAY_IO_MAP;
}
}
根据楼主的思路,照抄了一份 本帖最后由 zhouwenjing 于 2013-1-16 11:09 编辑
kevinstar888 发表于 2013-1-16 09:28 static/image/common/back.gif
根据楼主的思路,照抄了一份
这样做,也是可以的,但是局限性很大哦,这可不是我的思路,我的思路在下面。
进一步考虑的话,可以吧P0口和P2也采用查表方式:
把端口地址存放到一个数组里面
const INT8U RELAY_IO_MAP[]={1<<1,1<<7,1<<2,1<<5};
const INT8U PORT_MAP[]={ADDR_P0,ADDR_P0,ADDR_P2,ADDR_P2};
#define RELAY_COUNT (sizeof(RELAY_IO_MAP)/sizeof(*RELAY_IO_MAP))
void RelayOpen(int rid)
{
if((rid<=RELAY_COUNT)&&(rid>0))
{
*((INT8U *)PORT_MAP)|=RELAY_IO_MAP;
}
} 本帖最后由 NJ8888 于 2013-1-16 10:27 编辑
zhouwenjing 发表于 2013-1-16 09:18 static/image/common/back.gif
有吗,我怎么没有看到过呢??
能否截个图看看
你用bit band stm32上网找
例如点亮LED
// 使用STM32库
GPIO_ResetBits(GPIOC, GPIO_Pin_4); //关LED5
GPIO_SetBits(GPIOC, GPIO_Pin_7); //开LED2
// 一般读操作
STM32_Gpioc_Regs->bsrr.bit.BR4 =1;// 1:清除对应的ODRy位为0
STM32_Gpioc_Regs->bsrr.bit.BS7 =1;// 1:设置对应的ODRy位为1
//如果使用 位带别名区操作
STM32_BB_Gpioc_Regs->BSRR.BR =1;// 1:清除对应的ODRy位为0
STM32_BB_Gpioc_Regs->BSRR.BS =1;// 1:设置对应的ODRy位为1
代码比STM32库 高效 十倍 !
zhouwenjing 发表于 2013-1-16 09:52 static/image/common/back.gif
这样做,也是可以的,但是局限性很大哦,这可不是我的思路,我的思路在下面。
进一步考虑的话,可以吧P0 ...
如果我需要17个输出23个输入
这样写有可能写错
如果真要这样写还不如写成而为数组
至少可读性得到保证了
但是占空间 难到普通写法就不要空间了吗 whatcanitbe 发表于 2013-1-16 20:58:32 static/image/common/back.gif
如果我需要17个输出23个输入
这样写有可能写错
如果真要这样写还不如写成而为数组
至少可读性得到保证了
但是占空间
如果你写程序不细心,怎么写都会有错,
页:
[1]