qnx下的AD驱动

有没有谁在QNX系统下做过AD的驱动?我现在有一个项目,AD的中断一直出不来,不知道是哪里的问题

是不是你的DMA操作配置有问题呢?


或者先试试看查询模式 是不是能读到数据?

查询模式是可以的,而且采集出来的数据也是正确的。
但是通过定时器触发中断就不行了,我原来在winCE下做过AD的驱动。

“通过定时器触发中断”是什么 意思?要么是 “通过定时器”来定时查询(比如每100ms查询一次),要么是“通过AD触发中断”来实现。不知道你说的是哪一种情形。

不好意思,表达错误。
是用定时器输出信号的下降沿来触发AD转换,AD触发中断。
现在情况是可以进去中断服务函数,但是到InterruptWait()函数后就不往下走了。
寄存器操作部分应该是没有问题的

下面这个是个基本的 interrupt thread的例子。你在 main() 里 pthread_create() 这个线程就可以了(记得先ThreadCtl()取得io权限)

irq_id是中断号,do_irq_handling()是你真正操作硬件的函数。

void* isr_thread( void * arg )
{
	struct sigevent si;

	SIGEV_INTR_INIT( &si );
	InterruptAttachEvent(irq_id, &si, 0 );

	while( 1 )
	{
		InterruptWait( 0, NULL );
                do_isr_handling();
		InterruptUnmask( pub.irq, spec.iid );
	}

	InterruptDetach( spec.iid );
	return NULL;
}

xtang先生你好
我按照你的方法修改了我的程序,但是依然还是停留在InterruptWait()函数。
在main()函数调用ThreadCtl()函数和pthread_create()函数,我不知道在QNX下线程的优先级是不是也要修改?

InterruptWait()是应该阻塞的。只有当InterruptAttachEvent()所定的中断发生时,才会从阻塞状态中出来,执行后面的语句。

首先你能肯定 InterruptWait()被阻塞了吗?在后面加一句printf(“123\n”)什么的,看看会不会被打印到。

其它的就是你要肯定你用的irq_id是正确的吗?你可以试试挂时钟中断(1?),然后看看InterruptWait()会不会从阻塞状态中出来。
如果时钟中断可用,那就是你的irq_id所代表的中断没有被触发。

你可以提高线程的优先级,除非你在一个很忙的系统上,我不觉得你的线程会被任何别的线程挡住。

在InterruptWait()后加打印是出不来东西的,可以肯定是被阻塞了
将中断号改为时钟中断1,可以打印InterruptWait()后面的信息
那现在问题就是我的中断没有挂上,我今天将所有写到寄存器的值读出来没发现在设置上有问题
在main()函数中主要是设置通道范围、设置定时器的模式及分频值、设置定时器触发AD、并允许AD中断请求使能。方法使用的和wince下面的基本一样。

什么板子?你的中断配置得不对吧.

板子硬件跳线跳的中断7,bios里边也将中断7设置为ISA
中断服务函数里的irq_id用的也是7,其他地方还需要有设置的?
我在ISA总线上将中断7对应引脚硬连接一个高电平,发现也没有反应

ISA应是上升沿触发?将你的程序挂到时钟上,然后监视中断线的电压,看看是否有变化.

void* ISR_adt880(void *argment)
{
char ii;
struct sigevent si;

SIGEV_INTR_INIT(&si);
id = InterruptAttachEvent(IRQ_NUM,&si,0);
while(1)
{
InterruptWait(0,NULL);
#if ONE_CHANNEL
//单个通道
//delay(1);//1ms
adv = ADSample(BAADR);
printf("[ch=%2d] ADV=0x%04x Voltage=%8.5f(V)\r",ach,adv,ADCodeToVoltage(adv, modeval));

#else
//多个通道
for (ii=0; ii < 32; ii++)
{
if ( lastsedi == 0x60)
ach = rcount%32; //单端
else
ach = rcount%16; //双端
rcount++;
if((GetStatus(BAADR)&0x80)==0)
{
ReadAD(BAADR, &adv);
printf("[%X %6.3f]",ach,ADCode(adv, modeval));
}
if((ii+1)%32 == 0)
printf("\r\n");
}
#endif
ClrInt(BAADR);
InterruptUnmask(IRQ_NUM, id);
}
InterruptDetach(id);
return NULL;
}

int main(int argc, char *argv[])
{
int ThreadId;

ThreadCtl(_NTO_TCTL_IO,0);

BAADR = mmap_device_io(16,0x300);

ThreadId = pthread_create(NULL,NULL,&ISR_adt880,0);

//根据硬件跳线设置ADC
u8 ra = 1; //ADC模式设置

if (ra==0) {
modeval = 8;
adt880SetADBootMode(BAADR, modeval);
delay(10);//+
printf("-10~+10V\r\n");
SetADMode(BAADR, 1, 0, 0); // -10~+10V
}else if (ra==1) {
modeval = 0;
adt880SetADBootMode(BAADR, modeval);
delay(10);//+
printf(" -5~+5V \r\n");
SetADMode(BAADR, 0, 0, 0); // -5~+5V
}else if (ra==3) {
modeval = 12;
adt880SetADBootMode(BAADR, modeval);
delay(10);//+
printf(" 0~+10V \r\n");
SetADMode(BAADR, 1, 1, 0); // 0~+10V
}

SetCalMux(BAADR, 0);

//复位FIFO
FIFORst(BAADR);
//获得单端/双端设置
lastsedi = GetStatus(BAADR) & 0x60;
#if ONE_CHANNEL
//channel 0
SetADChannel(BAADR, 0, 0);
#else
if (lastsedi)
SetADChannel(BAADR, 31, 0); //单端.SE (channel 0~31)
else
SetADChannel(BAADR, 15, 0); //双端.DIF(channel 0~15)
#endif

TimerFRQ(BAADR, 0);
SetTimerMode(BAADR, 1, 3);
SetTimerDivisor(BAADR, 1, 50);

#if ONE_CHANNEL
SCANEN(BAADR, 0);
SetTimerMode(BAADR, 2, 3);
SetTimerDivisor(BAADR, 2, 300);
#else
SCANEN(BAADR, 1);
SetTimerMode(BAADR, 2, 3);
SetTimerDivisor(BAADR, 2, 200);
#endif
FIFOEN(BAADR, 1);
SetADTrigMode(BAADR, 3);
IRQenADDATimer(BAADR, 0); //使能AD中断的AINTE

//ClrInt(BAADR);
FIFOSet(BAADR);
}

使能FIFO和AD中断的AINTE时,FIFO中存放的采样点数达到设定的FIFO深度时,将 产生中断

小弟刚接触QNX没多长时间,求大家指教,这个问题已经困惑好久了

哪位高人帮忙看看程序哪里有问题,是不是流程不对啊?

问题解决了,在main函数的最后加上下面几句就可以了
ClrInt(BAADR);
while(1)
{
delay(100);
}