关于统一PLC编程标准几点说明
为了PLC程序可读性强,短期内可以读懂并且能够修改,在PLC工作组内部需要统一我们的编程标准,以便适应将来工程人员调动后,原来的程序能够被后来的人在短期内读懂,现统一标准如下:
一、程序结构
1、 程序结构统一
OB1:主程序;
OB100:初始化程序(无需主程序调用);
OB35:100ms(可修改)中断(无需主程序调用),可以调用PID模块;
OB80、OB82、OB85、OB86、OB87、OB121、OB122:故障诊断模块(无需主程序调用、无需编程);
FC1:系统模式;
FC2:输入处理;
FC3:输出处理;
FC4:运行处理;
FC5:停止处理;
FC6:手自动切换;
FC7:
。。。
。。。
FC100:之后用来建立一些可以循环调用的子程序;
FC105:系统自带,模拟量输入子程序(可以循环调用);
FC106:系统自带,模拟量输出子程序(可以循环调用);
modbus通讯(CP341):FB7:P_RCV_RK,FB8:P_SND_RK;
通讯CP340:FB2:P_RCV,FB3:P_SND;
一般PID:用FB41;
温、湿度PID:用FB58;
如果程序块与系
Linux内核的同步机制:原子操作(2009-06-24 23:19)
原子操作:UP和SMP的异同
原子操作是不可分割的,在执行完毕不会被任何其它任务或事件中断。在单处理器系统(UniProcessor)中,能够在单条指令中完成的操作都可以认为是'原子操作',因为中断只能发生于指令之间。这也是某些CPU指令系统中引入了test_and_set、test_and_clear等指令用于临界资源互斥的原因。但是,在对称多处理器(Symetric Multi-Processor)结构中就不同了,由于系统中有多个处理器在独立地运行,即使能在单条指令中完成的操作也有可能受到干扰。我们以decl(递减指令)为例,这是一个典型的'读-改-写'过程,涉及两次内存访问。设想在不同CPU运行的两个进程都在递减某个计数值,可能发生的情况是:
1. CPU A(上的进程,以下同)从内存单元把当前计数值(2)装载进它的寄存器中;
2. CPU B从内存单元把当前计数值(2)装载进它的寄存器中。
3. CPU A在它的寄存器中将计数值递减为1;
4. CPU B在它的寄存器中将计数值递减为1;
5. CPU A把修改后的计数值(1)写回内
LED驱动分析(2009-05-18 21:38)
void s3c2410_gpio_setpin(unsigned int pin, unsigned int
to)
{
void __iomem *base = S3C2410_GPIO_BASE(pin);
unsigned long offs = S3C2410_GPIO_OFFSET(pin);
unsigned long flags;
unsigned long dat;
local_irq_save(flags);
dat = __raw_readl(base + 0x04);
dat &= ~(1 << offs);
dat |= to << offs;
__raw_writel(dat, base + 0x04);
local_irq_restore(flags);
}
2410中的寄存器在I/O内存中根据0xF0000000这个base加上一个偏移值就简单的得到了VA,而且不同的寄存器偏移值都相差0x100000,比如
#define S3C24XX_VA_RTC
S3C2410_ADDR(0x00F00000)
#define S3C24XX_VA_GPIO
S3C2410_ADDR(0x00E00000)
#define S3C24XX_VA_IIS
S3C2410_ADDR(0x00D00000) 等等..
有个GPIO的虚拟地址base,接下来分析下面的:
#define S3C2410
内核驱动开发函数(四)(2009-04-18 10:43)
18、alloc_netdev()
alloc_netdev()函数生成一个net_device结构体,对其成员赋值并返回该结构体的指针。第一个参数是设备私有成员的大小,第二个参数为设备名,第三个参数为net_device的setup()函数指针。setup()函数接收的参数为struct
net_device指针,用于预置net_device成员的值。
出处linux-2.6.22/net/core/dev.c
----------------------------------------
struct net_device *alloc_netdev(int sizeof_priv, const char
*name,
void (*setup)(struct net_device *))
{
void *p;
struct net_device
*dev;
int alloc_size;
BUG_ON(strlen(name)
>= sizeof(dev->name));
alloc_size =
(sizeof(*dev) + NETDEV_ALI
内核驱动开发函数(三)(2009-04-18 10:41)
出处:/usr/src/linux-2.6.19/net/core/dev.c
int netif_rx(struct sk_buff *skb)
{
struct softnet_data *queue;
unsigned long flags;
if (netpoll_rx(skb))
return
NET_RX_DROP;
if (!skb->tstamp.off_sec)
net_timestamp(skb);
local_irq_save(flags);
queue = &__get_cpu_var(softnet_data);
__get_cpu_var(netdev_rx_s
内核驱动开发函数(二)(2009-04-18 10:39)
7、struct--resource
linux对挂接在4G总线空间上的设备实体的管理方式 -- struct resource
出处:/usr/src/linux-2.6.21.5/include/linux/ioport.h
struct resource {
resource_size_t start;
resource_size_t end;
const char
*name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};
struct resource_list {
struct resource_list *next;
struct resource
*res;
struct
pci_dev *dev;
};
一个独立的挂接在cpu总线上的设备单元,一般都需要一段线性的地址空间来描述设备自身,linux是怎么管理所有的这些外部'物理地址范围段',进而给用户和linux自身一个比较好
内核驱动开发函数(一)(2009-04-18 10:36)
GDT:全局描述符表
一般来说,段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation
fault就出现了.
在编程中以下几类做法容易导致段错误,基本是是错误地使用指针引起的
1)访问系统数据区,尤其是往 系统保护的内存地址写数据
最常见就是给一个指针以0地址
2)内存越界(数组越界,变量类型不一致等) 访问到不属于你的内存区域
解决方法
我们在用C/C++语言写程序的时侯,内存管理的绝大部分工作都是需要我们来做的。实际上,内存管理是一个比较繁琐的工作,无论你多高明,经验多丰富,难
免会在此处犯些小错误,而通常这
错误提示:
./tests: error while
loading shared libraries: xxx.so.0:cannot open shared object file:
No such file or directory
那就表示系统不知道xxx.so 放在哪个目录下。
这个时候就要在/etc/ld.so.conf中加入xxx.so所在的目录。
一般而言,有很多so档会在/usr/local/lib这个目录下,所以在/etc/ld.so.conf中加入/usr/local/lib这一行,可以解決此問題。
将 /etc/ld.so.conf存档后,还要执行「/sbin/ldconfig
–v」來更新一下才會生效。
unsigned int & int(2009-04-17 19:09)
unsigned int a = 6;
int b = -10;
int c = a + b;
cout<<a+b<<endl<<c<<endl;
输出的结果是4294967292和-4.从这里可以看出,a+b在计算的过程中,会把int转化成unsinged int 所以结果是个很大的数字,而当把unsinged
int型的数字赋值给int型的变量的时候,会默认转换成int型的,注意这是两种不同情况的转换,一种是在算术运算过程中,为了统一数值类型而发生的转换,另一种是赋值的时候产生的隐式转换。
另外不能出现 unsigned
double这样的写法,虽然在程序中也许没有错,但是浮点数本身就是有符号的数,unsigned和signed是修饰定点数的
对于 unsigned int a =
6;
double b =
-10;//float b = -10 一样的
int c = a + b;
cout<<