搜索
bottom↓
回复: 13

请教,51单片机,如何将IO端口作为形参传递给一个函数?

[复制链接]

出10入10汤圆

发表于 2021-12-29 08:22:28 | 显示全部楼层 |阅读模式
请教,51单片机,如何将IO端口作为形参传递给一个函数,这个函数根据不同的形参进行输入输出操作?
比如:
void PortOut(port,value)
{
   port = value;
}

void main()
{
   PortOut(P0,0x11);
   PortOut(P1,0x22);
}
这里只是简单的举例示意。

项目中经常会用到单片机驱动多个I2C芯片,每个芯片接的IO口不同,需要为每个芯片写同样的发送函数,如何简化为一个发送函数,形参是不同的IO,函数中根据传递的IO操作不同的芯片?

出10入10汤圆

 楼主| 发表于 2021-12-29 08:35:19 | 显示全部楼层
有些资料是这样说的:
C51对ANSI C做了一些扩展,针对单片机增加sfr16、sfr、sbit、bit数据类型,用它定义特殊功能寄存器、特殊功能寄存器位和位变量。相当于取个别名,方便操作,与普通变量又有区别,有的只能读,有的只能写,每个位都有具体的定义。
sfr是c51系列单片机扩充的类型,用来声明寄存器的。
编译器帮你做了转换例如 sfr P0 = 0x80;

P0 =3

逻辑上等价

*(byte*)80 = 3

但是程序不能这么写,为什么呢,这跟51单片机的哈弗结构有关系

出0入91汤圆

发表于 2021-12-29 08:40:07 | 显示全部楼层
里面PORT 的判断用 if吧

出200入2554汤圆

发表于 2021-12-29 08:49:17 | 显示全部楼层
标准 51 访问 IO 口,在硬件指令集层面,要么使用 SFR 直接寻址,要么使用按位直接寻址。
所谓直接寻址,就是一条指令访问哪个口,是在指令里写死的,而不能通过第三方寄存器来动态更改访问的 IO.

上述硬件结构决定了,51访问 IO 只能形如:

* (volatile byte *) 地址常数 = 0xXX

而不能使用:

* (volatile byte *) 地址变量 = 0xXX

因为后者需要产生间接寻址指令。
回到最开始的疑问,是否能用参数指定被访问的 IO?从间接寻址层面显然不行,但可以自己穷举,形如:

if( index==0 )
  P0_0= state;
else if(index==1)
  P0_1= state;
else if(index==2)
  P0_2= state;
else.....

出300入477汤圆

发表于 2021-12-29 08:55:45 来自手机 | 显示全部楼层
51系列的一个搞笑的设计,不存在指向sfr的指针。sfr只能被直接地址访问,通过指针访问的话你操作的是内与sfr同地址的普通内存
唯一的封装方法是上面说的,函数内部判断每个输入的sfr地址,然后执行直接访问

出0入309汤圆

发表于 2021-12-29 09:05:59 来自手机 | 显示全部楼层
架构原因楼上讲的都挺清楚。我是这么写的

https://github.com/DeqingSun/ch5 ... no/wiring_digital.c

出0入188汤圆

发表于 2021-12-29 09:29:12 | 显示全部楼层
这个我还真做了一个,方法可能比较笨,大概就是对每个Port口做一个Setbit 和ResteBit的函数,然后把这些port的函数做成两个指向函数指针的数粗,然后就可以了

出0入188汤圆

发表于 2021-12-29 09:43:21 | 显示全部楼层
方法笨是笨了点,可以参考参考













本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2021-12-29 11:29:20 | 显示全部楼层
可以参考ECBM库,我的做法就是建立一个gpio_in和gpio_out,把引脚作为参数。这样就可以复用软件IIC代码了

出0入37汤圆

发表于 2021-12-29 13:34:51 | 显示全部楼层
51里面io本身不是用户定义的变量,即便非得认为是变量的话,也是全局变量。因为io口本身就是那个地址,那个名字,而变量不单单是数据是可变的,其地址也是编译器在编译过程中自行指定的,不用也不能由编程者指定。

另外上面有人说51单片机是哈佛结构,那个真心不是,就像不能说原始社会是共产主义一样,虽然其存储区地址不是统一编制的,但是那是因为那个年代的局限性导致。哈佛结构的特点是数据存储器和程序存储器分别有各自的总线,当然也就有各自独立的地址,这个目的是为了能够同时访问数据存储器和程序存储器,,好处是可以流水线,一边执行前一条指令,一边把后一条指令就取出来了。51单片机明显不具备这个能力,12个clk才一个机器周期,肯定不是哈佛结构。

出0入8汤圆

发表于 2021-12-29 13:36:54 | 显示全部楼层
hjjnt2008 发表于 2021-12-29 09:43
方法笨是笨了点,可以参考参考

代码看起来顺眼

出145入215汤圆

发表于 2021-12-29 22:10:53 来自手机 | 显示全部楼层
sfr属于内部ram,51支持扩展外部ram为了。内外ram存在低段256字节地址重叠,所以在设计上分别用mov与movx 指令区分。在c这里体现就是可能同一条指令变汇编后有两条。简单理解就是想要把数据传到io结果数据传到相同地址的外部ram去了,操作无效果。汇编指令集层来看就是没有这条指令,地图未标注有这条路。硬件层就是根本没有这个电路。c语言用户,看到外面的马路想要从此处出去,结果碰到玻璃墙,能看到外面马路但是此路不通绕道通行。透光就是形容访问同地址的外部ram,出去指的是访问同地址的sfr。玻璃墙就是mcu内部具体电路。

出145入215汤圆

发表于 2021-12-29 22:30:07 来自手机 | 显示全部楼层
redroof 发表于 2021-12-29 08:55
51系列的一个搞笑的设计,不存在指向sfr的指针。sfr只能被直接地址访问,通过指针访问的话你操作的是内与sf ...

大神,如今看来这个设计搞笑。但是想想51内核可能是所知的处理器内核的祖宗,简称盘古。"51骂骂咧咧道,在坐各位处理器通通是我孙子"  标准51内核是可以扩展外部rom与外部ram的,别看只有40条腿,实力强的很。那个时代能支持64k的rom与ram简直不要太豪华。

出300入477汤圆

发表于 2021-12-30 08:44:02 来自手机 | 显示全部楼层
本帖最后由 redroof 于 2021-12-30 09:07 编辑
dz20062008 发表于 2021-12-29 22:30
大神,如今看来这个设计搞笑。但是想想51内核可能是所知的处理器内核的祖宗,简称盘古。"51骂骂咧咧道, ...


51并不是现代cpu的唯一祖先,在早期有一大堆流行的系列呢。甚至51的岀货量也不是最多的,好像最多的是6502,就是红白机和文曲星的cpu
只不过51系列是被国内最多的学校选做单片机课程教学的而已。不要神话它了。
相比之下6502还更接近现代处理器一点。统一的地址空间,外设都映射到内存。
从51以后就没什么单片机选择让外设和ram重叠只靠寻址方式区分了。这是个失败的尝试。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-20 15:16

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表