打印
[抢楼250]

菜地公告:即日起创建《菜农Cortex-M0助学园地》(盖楼入口)

[复制链接]
楼主: hotpower
手机看帖
扫描二维码
随时随地手机跟帖
2781
murex| | 2011-4-9 00:15 | 只看该作者 回帖奖励 |倒序浏览
int32_t DrvGPIO_SetBit(E_DRVGPIO_PORT port, int32_t i32Bit)
{
        GPIO_T * tGPIO;

    if ((i32Bit < 0) || (i32Bit > 16))
    {
        return E_DRVGPIO_ARGUMENT;
    }

        tGPIO = (GPIO_T *)((uint32_t)GPIOA + (port*PORT_OFFSET));  

        tGPIO->DOUT |= (1 << i32Bit);

        return E_SUCCESS;
}

使用特权

评论回复
2782
murex| | 2011-4-9 00:16 | 只看该作者
int32_t DrvGPIO_GetBit(E_DRVGPIO_PORT port, int32_t i32Bit)
{
    volatile uint32_t u32Reg;
        
    if ((i32Bit < 0) || (i32Bit > 16))
    {
        return E_DRVGPIO_ARGUMENT;
    }

    u32Reg = (uint32_t)&GPIOA->PIN + (port*PORT_OFFSET);   

    return ((inpw(u32Reg)>>i32Bit) & 0x1);
}

使用特权

评论回复
2783
murex| | 2011-4-9 00:16 | 只看该作者
int32_t DrvGPIO_GetBit(E_DRVGPIO_PORT port, int32_t i32Bit)
{
    volatile uint32_t u32Reg;
        
    if ((i32Bit < 0) || (i32Bit > 16))
    {
        return E_DRVGPIO_ARGUMENT;
    }

    u32Reg = (uint32_t)&GPIOA->PIN + (port*PORT_OFFSET);   

    return ((inpw(u32Reg)>>i32Bit) & 0x1);
}

使用特权

评论回复
2784
murex| | 2011-4-9 00:16 | 只看该作者
2785
murex| | 2011-4-9 00:17 | 只看该作者
神马骑蜗牛,浮云要落地
晕,助学开发板及助学简易Nulink终于可以全面发货了,好事多磨难,整整推迟了一个月!!!
前后起伏荡漾,艰难曲折,令菜农每日都要向网友致歉...
在这期间,俺每天都要向想购置助学板的网友说先不要在淘宝拍,再等…

使用特权

评论回复
2786
murex| | 2011-4-9 00:17 | 只看该作者
菜农新唐Cortex-M0助学开发板即日起陆续发货



     首先菜农在这里向网友表示最沉痛地道歉!!!并致以革命的敬礼!!!
原本计划在2.18开始的助学活动几乎被迫延迟了一个月时间,实际样板早好…

使用特权

评论回复
2787
murex| | 2011-4-9 00:17 | 只看该作者
哈哈,乱七八糟

使用特权

评论回复
2788
murex| | 2011-4-9 00:17 | 只看该作者
怎么还是没人来顶

使用特权

评论回复
2789
murex| | 2011-4-9 00:18 | 只看该作者
菜农贴
我最近用单片机模拟I2C做slave,现在做出来了,但是误码率很高,检查了一下原因,是地址经常读错,还有的是地址读到之后没有给主机应答。我检测时钟信号是用while语句写的,下面是我写的接收一个字节数据的程序:
uchar RcvB()
{
。。。。。。
}
首先很少人有这个想法,但模拟主机很普遍。
模拟I2C主机是可行的,因为时钟SCL由主机提供,MCU很容易掌控。
但是模拟I2C从机的难度要大很多。
首先SCL由主机提供,有效地捕捉和跟随它要看主机的速率而定。
所以选择模拟从机应该是个错误,但又带来了可行性的讨论。
一般IO模拟有2种方法:中断或查询。
由于中断有着固定的响应时间,再加上到中断的有效处理处的时间,可能信号早已翻转,此时有不如简单的IO查询了。
所以要根据主机速率来选择IO模拟的方式。
真正满足I2C协议的主机有个很重要的特性:
允许从机拉低时钟降速。
这就告诉我们模拟从机是可行的,虽然并不合理。
考虑到中断嵌套和中断响应时间等问题,我认为查询比中断会好些。(当主机速率低是中断是很好的选择)
但这又带来了CPU占有率的问题。
因为while(SCL)或while(!SCL)会使其他任务阻塞,故裸奔时其他程序
应该由定时中断及其他中断激活,OS时由高优先级任务激活。
这样做问题又来了---其他任务打断了I2C协议的次序。
所以程序应该采用协作式,即在主机SCL=0时:
首先从机拉低SCL=0!!!
若需从机发送数据,此时从机可以发送SDA.
然后开中断在其他任务中断时把控制权让出。
当从机程序重新获取控制权后,再关中断后释放SCL=1.
再用while(!SCL)捕捉SCL的上升沿后来读取SDA数据。
总之模拟从机很困难,成功的前提时:
必须捕捉到SCL=0而不丢失一次。
要做到这个可以选择外部中断为最高级中断。但中断响应时间
必须小于SCL=0的脉宽,否则只能采用查询方法。

使用特权

评论回复
2790
murex| | 2011-4-9 00:18 | 只看该作者
疯狂冲刺

使用特权

评论回复
2791
murex| | 2011-4-9 00:18 | 只看该作者
HRESULT CVIFUNC I2C_Start(void)
{
    HRESULT __result = S_FALSE;
    int i;
    unsigned char ack;
    for (i = 0; i < I2C_waitStartDelay;i ++) {
        ack = I2C_GetSDA();//释放数据总线读数据总线
        I2C_SetSCL();//首先拉高SCL, 保证SDA在SCL=1时跳变,拉高时钟(必须在SDA=1时)
        I2C_ClrSDA();//首先拉低SDA.必须按次序!!!
        I2C_ClrSCL();//然后拉低SCL,构成I2C从机内部中断并唤醒
        if (ack) {//测试成功!!!总线已释放
            __result = S_OK;//
            break;
        }
    }

使用特权

评论回复
2792
murex| | 2011-4-9 00:19 | 只看该作者
if (__result == S_OK)
    {
        Hot_I2CErrorState = I2C_START;//已发送起始条件
    }
    else
    {
        Hot_I2CErrorState = -1;//未发送起始条件
        I2C_Stop ();
    }
    return __result;
}

使用特权

评论回复
2793
murex| | 2011-4-9 00:19 | 只看该作者
HRESULT CVIFUNC I2C_ReStart(unsigned char addrss)
{
    HRESULT __result;
//入口:SDA=SCL=0
    I2C_SetSDA();//首先拉高SDA, 这样才能保证在SCL=1时SDA下跳构成再次复位条件即复位
    I2C_SetSCL();//然后拉高SCL, 保证SDA在SCL=1时跳变,拉高时钟(必须在SDA=1时)
    I2C_ClrSDA();//首先拉低SDA.必须按次序!!!
    I2C_ClrSCL();//然后拉低SCL,构成I2C从机内部中断并唤醒
    I2C_ReadWriteByte (addrss | 1);//强行发送I2C读地址,SDA=SCL=0
    __result =I2C_GetAck();//取从机ACK信号
    if (__result == S_OK)
    {
        Hot_I2CErrorState = I2C_MT_SLA_ACK;//已发送SLA+W,且已接收ACK
    }
    else
    {
        Hot_I2CErrorState = I2C_MT_SLA_NACK;//已发送SLA+W,且未接收ACK
        I2C_Stop ();
    }
    return __result;
}

使用特权

评论回复
2794
murex| | 2011-4-9 00:19 | 只看该作者
void CVIFUNC I2C_Stop (void)
{
    I2C_ClrSCL();
    I2C_ClrSDA();
      I2C_SetSCL();//在SCL为高时准备Stop信号,拉高时钟(必须在SDA=1时,故本例形成Stop())
      I2C_SetSDA();//STOP信号结束
}

使用特权

评论回复
2795
murex| | 2011-4-9 00:19 | 只看该作者
void CVIFUNC I2C_WriteAck(unsigned char ack)
{
    if (ack) {
        I2C_ClrSDA();//给从机ACK信号
    }
    else
    {
        I2C_SetSDA();//给从机nACK信号
    }
    I2C_SetSCL();//拉高时钟信号,拉高时钟(必须在SDA=1时)
    I2C_ClrSCL();//拉低时钟信号,防止START信号产生
    I2C_ClrSDA();//给从机ACK信号
}

使用特权

评论回复
2796
murex| | 2011-4-9 00:19 | 只看该作者
HRESULT CVIFUNC I2C_GetAck(void)
{
    HRESULT __result = S_FALSE;
    int i;
    for (i = 0; i < I2C_waitAckDelay; i ++)
    {
        if (I2C_GetSDA() == 0) //释放数据总线读数据总线
        {
            __result = S_OK;
            break;
        }
    }
    I2C_SetSCL();//拉高时钟(必须在SDA=1时)???
    I2C_ClrSCL();//拉低时钟
    I2C_ClrSDA();//保证SDA=SCL=0///pwy(拉低SDA便于发送停止喜欢)
    return __result;//SDA=1,SCL=0
}

使用特权

评论回复
2797
murex| | 2011-4-9 00:19 | 只看该作者
/*-----------------------------------------------------------
    I2C一体化读写程序
-------------------------------------------------------------*/
unsigned char CVIFUNC I2C_ReadWriteByte(unsigned char value)
{
    int i;
    for (i = 0; i < 8; i ++)//每个字节8位
    {
        if (value >= 0x80) //D7位=1
        {
             value <<= 1;//I2C协议先出D7位
            I2C_SetSDA();
            if (I2C_GetSDA())//GetSDA()内带释放数据总线SetSDA()
            {
                value ++;//读回1位I2C数据1
            }
        }
        else//D7=0
        {
             value <<= 1;//I2C协议先出D7位
            I2C_ClrSDA();//写入1位I2C数据0
        }
        I2C_SetSCL();//拉高I2C时钟
        I2C_ClrSCL();//拉低I2C时钟
    }
    I2C_ClrSDA();//保证出口SDA=SCL=0
    return value;//返回数据
}

使用特权

评论回复
2798
murex| | 2011-4-9 00:20 | 只看该作者
unsigned char CVIFUNC I2C_ReadByte (unsigned char ack)
{
    unsigned char value;
    value = I2C_ReadWriteByte (0xff);//取数据
    I2C_WriteAck(ack);//向从机发送ACK/nACK信号  
    return value;//返回接收数据
}

使用特权

评论回复
2799
murex| | 2011-4-9 00:20 | 只看该作者
unsigned short CVIFUNC I2C_ReadWord (unsigned char ack)
{
    unsigned short value;
    unsigned char ch, cl;
    cl = I2C_ReadByte (I2C_ACK);
    if (ack) ch = I2C_ReadByte (I2C_ACK);
    else ch = I2C_ReadByte (I2C_nACK);
    value = (ch << 8) | cl;
    return value;
}

使用特权

评论回复
2800
murex| | 2011-4-9 00:20 | 只看该作者
void CVIFUNC I2C_ReadBlock (unsigned char *str, int size)
{
    int i;
    for (i = 0; i < size; i ++)
    {
        if (i == size - 1)
        {
            str[i] = I2C_ReadByte(I2C_nACK);
        }
        else
        {
            str[i] = I2C_ReadByte(I2C_ACK);
        }
    }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则