SLEEP函数解决C中断在WINDWOS中占CPU问题_暗留香_百度空间

程序作用:播放WAV声音。DOS播放任意长度WAV音乐。

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <mem.h>
#include <dos.h>
/* 以下是 PC 机的 DMA 控制器端口的常量定义 */
#define DMA8_CMD_PORT      0x08   /* 8位DMA写命令寄存器端口 */
#define DMA8_STATU_PORT    0x08   /* 8位DMA独状态寄存器端口 */
#define DMA8_REQUEST_PORT 0x09   /* 8位DMA写请求寄存器端口 */
#define DMA8_MASK_PORT     0x0A   /* 8位DMA屏蔽寄存器端口(只写)*/
#define DMA8_MODE_PORT     0x0B   /* 8位DMA写模式寄存器端口 */
#define DMA8_CLRPTR_PORT   0x0C   /* 8位DMA清先后状态寄存器端口 */
#define DMA8_RESET_PORT    0x0D   /* 8位DMA写复位命令端口 */

/* 以下是 PC 机 DMA 的 7 个通道的地址寄存器、计数寄存器和页面寄存器的端口常量定义 */
/* 其中通道 0-3 用于 8 位的 DMA,通道 4-7 用于 16 位 DMA */
/* PC机中,规定通道 2 用于进行软盘的 DMA 传输,其余通道可供用户使用 */
#define DMA0_ADDR_PORT     0x00   /* 通道0的地址寄存器 */
#define DMA0_COUNT_PORT    0x01   /* 通道0的计数寄存器 */
#define DMA0_PAGE_PORT     0x87   /* 通道0的页面寄存器 */

#define DMA1_ADDR_PORT     0x02   /* 通道1的地址寄存器 */
#define DMA1_COUNT_PORT    0x03   /* 通道1的计数寄存器 */
#define DMA1_PAGE_PORT     0x83   /* 通道1的页面寄存器 */

#define DMA3_ADDR_PORT     0x06   /* 通道3的地址寄存器 */
#define DMA3_COUNT_PORT    0x07   /* 通道3的计数寄存器 */
#define DMA3_PAGE_PORT     0x82   /* 通道3的页面寄存器 */

#define DMA5_ADDR_PORT     0xC4   /* 通道5的地址寄存器 */
#define DMA5_COUNT_PORT    0xC6   /* 通道5的计数寄存器 */
#define DMA5_PAGE_PORT     0x8B   /* 通道5的页面寄存器 */

#define DMA6_ADDR_PORT     0xC8   /* 通道6的地址寄存器 */
#define DMA6_COUNT_PORT    0xCA   /* 通道6的计数寄存器 */
#define DMA6_PAGE_PORT     0x89   /* 通道6的页面寄存器 */

#define DMA7_ADDR_PORT     0xCC   /* 通道7的地址寄存器 */
#define DMA7_COUNT_PORT    0xCE   /* 通道7的计数寄存器 */
#define DMA7_PAGE_PORT     0x8A   /* 通道7的页面寄存器 */

/* DSP 定义 */
#define DSP_RESET_DELAY   10
#define DSP_READY         0xAA

#define DSP_GET_VERSION   0xE1
#define DSP_SET_BLK_SIZE 0x48
#define DSP_START_DMA8    0x1C
#define DSP_PAUSE_DMA8    0xD0
#define DSP_SET_SAM_RATE 0x40

#define PIC_PORT_21H 0x21
#define PIC_PORT_20H 0x20
#define PIC_EOI       0x20
/*数据块大小必须<51199*/
#define DMA_BUFFER_SIZE 51198
#define TRUE 1
#define FALSE 0

typedef struct
{
    unsigned short wavetype;    /* WAVE的类别   */
    unsigned short channel;     /* 通道数       */
    unsigned short samplerate; /* 采样频率     */
    unsigned short samplebits; /* 采样位数     */
    long int datalen;     /* 数据长度     */
    long int leftdatalen; /* 剩余数据长度 */
    int   loops;       /* 播放次数     */
    FILE *fp;
} WAVE, *PWAVE;

typedef struct
{
    char dspenvstr[128];
    unsigned short dspversion;
    unsigned short dspbaseioport;
    unsigned short resetport;
    unsigned short writedataport;
    unsigned short writestatusport;
    unsigned short readdataport;
    unsigned short readstatusport;
    unsigned short mixerbaseioport;
    unsigned short mpu401baseioport;
    unsigned char dspirqnum;
    unsigned char dspdma8;
    unsigned char dspdma16;
} DSP, *PDSP;

/* WAVE 文件结构定义 */
typedef struct
{
    char RIFF[4];     /* RIFF         */
    unsigned long int filelen;     /* 文件长度     */
    char WAVEfmt[8]; /* WAVEfmt      */
    unsigned long int reserved;    /* 保留         */
    unsigned short wavetype;    /* WAVE的类别   */
    unsigned short channel;     /* 通道数目     */
    unsigned short sampling;    /* 采样频率     */
    unsigned long int transpeed;   /* 数据传输速率 */
    unsigned short blkalign;    /* 调整数据块   */
    unsigned short sampbits;    /* 采样位数     */
    char data[4];     /* data         */
    unsigned long int datalen;     /* 语音数据长度 */
    unsigned char *pdata;       /* 数据区       */
} WAVEFILE, *PWAVEFILE;


int initsound(void);
void closesound(void);
int loadwave(PWAVE pwave, char *file);
void destroywave(PWAVE pwave);
void playwave(PWAVE pwave);
void stopwave(PWAVE pwave);
void pausewave(PWAVE pwave);
int initpic(int irqnum);
void closepic(int irqnum);
void picintdone(void);

int initdsp(PDSP pdsp);

void writedsp(PDSP pdsp, unsigned char byte);
void setdspblocksize(PDSP pdsp, unsigned short blksize);
void dspstartdma8(PDSP pdsp);
void dsppausedma8(PDSP pdsp);
void dspsetsamplerate(PDSP pdsp, unsigned short rate);

int initdma8(int channel, unsigned char far *addr, int size);
void closedma8(int channel);
void interrupt (*old_dsp_int_handle)(void) = NULL;

void interrupt new_zhong_duan(void);
void an_zhuang_zhong_duan(void);
void del_zhong_duan(void);


DSP   cursbdsp     = {0};
PWAVE pcurwave     = NULL;
int dma_buf_flag = NULL;
unsigned char far *sound_dma_buf = NULL;

int parse_sb_envstr(char *envstr, char id);


int initdma8(int channel, unsigned char far *addr, int size)
{
    unsigned long phyaddr = FP_SEG(addr) * 0x10L + FP_OFF(addr);
    unsigned char page    = (unsigned char)(phyaddr >> 16);
    unsigned short   offset = (unsigned short)(phyaddr >> 0);
    outportb(DMA8_MASK_PORT, channel | (1 << 2)); /* 屏蔽该通道 */
    outportb(DMA8_MODE_PORT, channel | (1 << 4) | (2 << 2)); /* 请求方式+自动初始化+读传送 */
    outportb(DMA8_CLRPTR_PORT, 0);

    outportb(DMA1_COUNT_PORT, (size - 1)& 0x00FF);
    outportb(DMA1_COUNT_PORT, (size - 1) >> 8);
    outportb(DMA1_ADDR_PORT, (offset)& 0x00FF);
    outportb(DMA1_ADDR_PORT, (offset) >> 8);
    outportb(DMA1_PAGE_PORT, page);

    outportb(DMA8_MASK_PORT, channel);
    return TRUE;             
}

void closedma8(int channel)
{
    if (channel > 3 || channel == 2) return;
    outportb(DMA8_MASK_PORT, channel | (1 << 2)); /* 屏蔽该通道 */
}


int parse_sb_envstr(char *envstr, char id)
{
    char buf[32] = "0x";
    int i;
    int j;

    for (i = 0; envstr[i] != id && envstr[i] != '\0' && i < 128; i++);
    if (envstr[i] == '\0' || i == 128) return 0;
    else i++;
    for (j = 2; j < 32 && envstr[i] != ' '; j++) buf[j] = envstr[i++];
    return (int)strtoul(buf, NULL, 0);
}

/* 函数实现 */
int initdsp(PDSP pdsp)
{
    if (!getenv("BLASTER")) return FALSE;
    strupr(strcpy(pdsp->dspenvstr, getenv("BLASTER")));

    pdsp->dspbaseioport    = parse_sb_envstr(pdsp->dspenvstr, 'A');
    pdsp->resetport        = pdsp->dspbaseioport + 0x06;   /*复位端口*/
    pdsp->writedataport    = pdsp->dspbaseioport + 0x0C;    /*写数据端口*/
    pdsp->writestatusport = pdsp->dspbaseioport + 0x0C;     /*写状态端口*/
    pdsp->readdataport     = pdsp->dspbaseioport + 0x0A;    /*读数据端口*/
    pdsp->readstatusport   = pdsp->dspbaseioport + 0x0E;    /*读状态端口*/
    pdsp->dspirqnum        = parse_sb_envstr(pdsp->dspenvstr, 'I');
    pdsp->dspdma8          = parse_sb_envstr(pdsp->dspenvstr, 'D');
    pdsp->dspdma16         = parse_sb_envstr(pdsp->dspenvstr, 'H');
    pdsp->mixerbaseioport = parse_sb_envstr(pdsp->dspenvstr, 'M');
    pdsp->mpu401baseioport = parse_sb_envstr(pdsp->dspenvstr, 'P');


    writedsp(pdsp, DSP_GET_VERSION);
    return TRUE;
}

void writedsp(PDSP pdsp, unsigned char byte)
{

    outportb(pdsp->writedataport, byte);
}

void setdspblocksize(PDSP pdsp, unsigned short blksize)
{
    writedsp(pdsp, DSP_SET_BLK_SIZE);
    writedsp(pdsp, (blksize - 1) &0x00FF);
    writedsp(pdsp, (blksize - 1) >> 8);
}


void dspstartdma8(PDSP pdsp)
{
    writedsp(pdsp, DSP_START_DMA8);
}

void dsppausedma8(PDSP pdsp)
{
    writedsp(pdsp, DSP_PAUSE_DMA8);
}

void dspsetsamplerate(PDSP pdsp, unsigned short rate)
{
    unsigned short timeconst = (unsigned short)(65536L - (256000000L / rate));
    writedsp(pdsp, DSP_SET_SAM_RATE);
    writedsp(pdsp, timeconst >> 8);
}

int initpic(int irqnum)
{
    unsigned char mask;
    mask = inportb(PIC_PORT_21H);
    mask &= ~(1 << irqnum);
    outportb(PIC_PORT_21H, mask);
}

void closepic(int irqnum)
{
    unsigned char mask;
    mask = inportb(PIC_PORT_21H);
    mask |= (1 << irqnum);
    outportb(PIC_PORT_21H, mask);
}

void picintdone(void)
{
    outportb(PIC_PORT_20H, PIC_EOI); /* 写中断结束命令 */
}

int initsound(void)
{
    sound_dma_buf = (unsigned char far *)malloc(DMA_BUFFER_SIZE);
    if (!sound_dma_buf) return FALSE;
    initdsp(&cursbdsp);
    setdspblocksize(&cursbdsp, DMA_BUFFER_SIZE / 2);
    initdma8(cursbdsp.dspdma8, sound_dma_buf, DMA_BUFFER_SIZE);
    initpic(cursbdsp.dspirqnum);
    an_zhuang_zhong_duan();
    return TRUE;
}

void closesound(void)
{
    del_zhong_duan();
    closepic(cursbdsp.dspirqnum);
    closedma8(cursbdsp.dspdma8);

    if (sound_dma_buf) free((void*)sound_dma_buf);
}

/* 装载WAVE 文件到 WAVE 对象 */
int loadwave(PWAVE pw, char *file)
{
    WAVEFILE wf;

    pw->fp = fopen(file,"rb");
    if (!pw->fp) return FALSE;

    fread(&wf, sizeof(wf), 1, pw->fp);
    pw->wavetype    = wf.wavetype;
    pw->channel     = wf.channel;
    pw->samplerate = wf.sampling;
    pw->samplebits = wf.sampbits;
    pw->datalen     = wf.filelen - sizeof(wf) - 14;
    pw->leftdatalen = wf.filelen - sizeof(wf) - 14;
    fseek(pw->fp, 14, SEEK_CUR);
    return TRUE;
}

/* 销毁 WAVE 对象 */
void destroywave(PWAVE pw)
{
    fclose(pw->fp);
    pw->fp = NULL;
}

void playwave(PWAVE pwave)
{
    pcurwave     = pwave;
    dma_buf_flag = FALSE;
    fread((void*)sound_dma_buf, DMA_BUFFER_SIZE, 1, pcurwave->fp);
    initdma8(cursbdsp.dspdma8, sound_dma_buf, DMA_BUFFER_SIZE);
    dspsetsamplerate(&cursbdsp, pcurwave->samplerate*pcurwave->channel);
    dspstartdma8(&cursbdsp);
}

void stopwave(PWAVE pwave)
{
    dsppausedma8(&cursbdsp);
    fseek(pcurwave->fp, sizeof(WAVEFILE) + 14, SEEK_SET);
    pwave->leftdatalen = pwave->datalen;
}

void pausewave()
{
    dsppausedma8(&cursbdsp);
}

/* 内部函数实现 */
void interrupt new_zhong_duan(void)
{
    pcurwave->leftdatalen -= DMA_BUFFER_SIZE / 2;
    fread((void*)(sound_dma_buf + dma_buf_flag * DMA_BUFFER_SIZE / 2),1, DMA_BUFFER_SIZE / 2, pcurwave->fp);
    dma_buf_flag = ! dma_buf_flag;
    picintdone();
    sleep(1);

}

void an_zhuang_zhong_duan(void)
{
    old_dsp_int_handle = getvect(cursbdsp.dspirqnum + 8);
    setvect(cursbdsp.dspirqnum + 8, new_zhong_duan);
}

void del_zhong_duan(void)
{
    setvect(cursbdsp.dspirqnum + 8, old_dsp_int_handle);
    old_dsp_int_handle = NULL;
}

main()
{
    WAVE mywave = {0};
    initsound();
    loadwave(&mywave, "test.wav");
    mywave.loops = -1;
    playwave(&mywave);
    getch();
    destroywave(&mywave);
    closesound();
}

成功解决C语言中断占用CPU问题~

哈哈,乱说的。只是用SLEEP函数把程序挂起。没办法WINDWOS操作系统支持的不是很好。

我发现添加个SLEEP函数后,杂音没了!

添加个键盘中断,想控制。没成功。开始是在main函数中动手脚,添加个判断:while(sigh) printf("1");

sigh初始值是1,判断键盘按下后值为0,但是,在main中循环时间只是从DMA一个块播放完毕就不循环了。应该是被SLEEP挂起了。

纠结!

在键盘中断服务程序中禁止中断:

int initpic((int)&new_zhong_duan);

未成功。

程序总是无法自己结束。({dy}个块播放之后按)

有时间继续。。。睡觉。

键盘中断代码:
void   keyboard(void)    //设置中断
{  
          oldint   =   getvect(9);  
          setvect(9,newint);  
}  
   
void interrupt   newint() //服务程序
{


}  

void huifu()

{

setvet(9,oldint);

}



郑重声明:资讯 【SLEEP函数解决C中断在WINDWOS中占CPU问题_暗留香_百度空间】由 发布,版权归原作者及其所在单位,其原创性以及文中陈述文字和内容未经(企业库qiyeku.com)证实,请读者仅作参考,并请自行核实相关内容。若本文有侵犯到您的版权, 请你提供相关证明及申请并与我们联系(qiyeku # qq.com)或【在线投诉】,我们审核后将会尽快处理。
—— 相关资讯 ——