发现GD32F150C8T6芯片的几个问题

[复制链接]
3119|16
 楼主 | 2015-4-16 15:51 | 显示全部楼层 |阅读模式
问题一:ADC模块的中断需要写两次清除中断标志寄存器才能清除中断,测试代码如下:

#define TESTPIN_ON()                GPIOA->BOR = (1UL << 2)                        //PA2拉高
#define TESTPIN_OFF()        GPIOA->BOR = (1UL << 18)                        //PA2拉低
#define WAITE_NOP()                __nop();__nop();__nop();        \
                                        __nop();__nop();__nop();        \
                                        __nop();__nop();__nop();        \
                                        __nop();__nop();__nop()
/****************************************************************************
** 函数名称 :void ADC_Init (VMEAS *v)
** 函数功能 :ADC初始化
****************************************************************************/
void ADC_Init (void)
{       
        RCC->APB2RCR |= RCC_APB2RCR_ADC1RST;        //复位ADC1
        RCC->APB2RCR &= ~RCC_APB2RCR_ADC1RST;        //复位关闭

        RCC->APB2CCR |= RCC_APB2CCR_ADC1EN;                //开启ADC时钟
        RCC->AHBCCR  |= RCC_AHBCCR_PAEN;                //使能引脚时钟PA
       
        RCC->GCFGR   |= RCC_GCFGR_ADCPS_DIV4;        //ADC时钟4分频,12MHz
        RCC->GCFGR3  |= (1UL << 8);                                //ADC时钟源选择  0:HSI14  1:APB2
        WAITE_RCC();                                                        //等待时钟稳定
       
        GPIOA->CTLR |= (GPIO_CTLR_CTLR0 |                 //PA0配置为ADCIN0
                                    GPIO_CTLR_CTLR1 |                 //PA1配置为ADCIN1
                                        GPIO_CTLR_CTLR3 );                //PA3配置为ADCIN3                       
       
        ADC1->ISQ = (2UL << 20) |                                //注入转换3个通道  2+1
                                (0UL << 5 ) |                                //ADCIN0
                                (1UL << 10) |                                //ADCIN1
                                (3UL << 15) ;                                //ADCIN3
       
        /*设置通道的采样时间为7.5个周期*/
        ADC1->SPT2 &= ~(ADC_SPT2_SPT0 | ADC_SPT2_SPT1 | ADC_SPT2_SPT3);
        ADC1->SPT2 |= ADC_SPT2_SPT0_0 | ADC_SPT2_SPT1_0 | ADC_SPT2_SPT3_0;       

        ADC1->CTLR1 = (1UL << 8) |                                //开启扫描模式
                                  (1UL << 7) ;                                //允许注入通道转换结束中断

        ADC1->CTLR2 = (1UL << 15) |                                //注入组外部触发使能
                                  (0UL << 12) |                                //TIM1_TRGO事件触发
                                  (0UL << 11) |                                //数据右对齐
                                  (0UL << 8 ) ;                                //不使用DMA
                                  
        ADC1->CTLR2 |= ADC_CTLR2_ADCON;                        //开启ADC
       
        ADC1->CTLR2 |= ADC_CTLR2_RSTCLB;                //复位校准寄存器
        while(ADC1->CTLR2 & ADC_CTLR2_RSTCLB);
       
        ADC1->CTLR2 |= ADC_CTLR2_CLB;                        //校准ADC
        while(ADC1->CTLR2 & ADC_CTLR2_CLB);
       
        ADC1->STR &= ~(1UL << 2);                                //清除标志位
       
        NVIC_EnableIRQ(ADC1_CMP_IRQn);                        //允许中断
}

/****************************************************************************
** 函数名称 :void ADC1_CMP_IRQHandler (void)
** 函数功能 :ADC1中断处理
****************************************************************************/
void ADC1_CMP_IRQHandler (void)
{
        adc1.ADCRes[ADC_HB]   = ADC1->IDTR1;               
        adc1.ADCRes[ADC_MPV]  = ADC1->IDTR2;               
        adc1.ADCRes[ADC_HALL] = ADC1->IDTR3;               

        TESTPIN_ON();
        WAITE_NOP();       
               TESTPIN_OFF();
       
        ADC1->STR &= ~(ADC_STR_STIC | ADC_STR_EOIC);    //用示波器查看TESTPIN电平,发现中断处理函数连续进来了两次。
                                                                                    //如果这条语句让他执行两次或者先清EOIC再清STIC标志,中断处理函数恢复正常(不再连续进来)
}

问题二:将TIM3配置成霍尔传感器输入接口后,在TIM3_CH1 (PA6)、TIM3_CH2 (PA7)、TIM3_CH3 (PB0)上通过4.7K电阻上拉到5V。发现上述配置的ADC_IN0上存在向外的灌电流200uA左右。而且在ADC被外部触发信号触发转换时,ADC_IN0上的电压会不断波动。

问题三:SPI模块抗干扰能力偏弱。在SPI模块在发送数据时,如果用示波器表笔点SCK这个信号线(点在与这个信号相连的外部10K上拉电阻上)。通过多次点击测试后,SPI的内部移位寄存器会发生移位现象。我猜测内部移位寄存器的移位CLK与SPI接口的SCK信号共用,但是外部和内部没有输出缓冲器,所以在对这个SCK信号进行干扰时,直接影响了内部移位寄存器移位。以下是初始化代码:
/*****************************************************************************
** 函数名称 :void SPI1_Reset (void)
** 函数功能 :重置SPI
*****************************************************************************/
static void SPI1_Reset (void)
{
        RCC->APB2RCR |= RCC_APB2RCR_SPI1RST;                //复位SPI1
        RCC->APB2RCR &= ~RCC_APB2RCR_SPI1RST;                //复位关闭
        RCC->APB2CCR |= RCC_APB2CCR_SPI1EN;              //使能SPI1时钟
        WAITE_RCC();                                                                //等待时钟稳定
       
        SPI1->CTLR1 &= ~SPI_CTLR1_SPIEN;                        //关闭SPI设备
       
        SPI1->CTLR1  =         (1UL << 15)|                                //选择单向单线模式
                                        (1UL << 14)|                                //发送模式
                                        (0UL << 11)|                                //数据长度为8位
                                        (1UL << 9) |                                //启用软件从设备管理
                                        (1UL << 8) |                                //主模式
                                        (0UL << 7) |                                //先发LSB
                                        (4UL << 3) |                                 //Fsck=Fcpu/32
                                        (1UL << 2) |                                //配置设备模式                  0:从设备           1:主设备
                                        (1UL << 1) |                                //空闲状态SCK电平          0:低电平          1:高电平
                                        (1UL << 0);                                        //数据采样                        0:第一个时钟边沿         1:第二个时钟边沿
       
        SPI1->CTLR2 = 0;                                       

        SPI1->CTLR1 |= SPI_CTLR1_SPIEN;                                //开启SPI设备
}

/*****************************************************************************
** 函数名称 :void SPI1_Init (void)
** 函数功能 :SPI初始化
*****************************************************************************/
void SPI1_Init (void)
{
        RCC->AHBCCR |= RCC_AHBCCR_PAEN;                                                        //使能引脚时钟PA
        RCC->AHBCCR |= RCC_AHBCCR_PBEN;                                                        //使能引脚时钟PB
        WAITE_RCC();                                                                                        //等待时钟稳定
       
        /*初始化SPI1管脚*/
        GPIOA->CTLR  &= ~GPIO_CTLR_CTLR15;
        GPIOA->CTLR  |= GPIO_CTLR_CTLR15_0;                                                //PA15配置为CS
       
        GPIOA->OMODE &= ~GPIO_OMODE_OM15;                                                //推挽输出
        GPIOA->OSPD  &= ~GPIO_OSPD_OSPD15;
       
        CLR_NSS;
       
        GPIOB->CTLR  &= ~(GPIO_CTLR_CTLR3 | GPIO_CTLR_CTLR5);
        GPIOB->CTLR  |= GPIO_CTLR_CTLR3_1 | GPIO_CTLR_CTLR5_1;
       
        GPIOB->OMODE &= ~(GPIO_OMODE_OM3 | GPIO_OMODE_OM5);                //推挽输出
        GPIOB->OSPD  &= ~(GPIO_OSPD_OSPD3 | GPIO_OSPD_OSPD5);
        GPIOB->OSPD  |= GPIO_OSPD_OSPD3_0 | GPIO_OSPD_OSPD5_0;
       
        GPIOB->AFS[0] &= ~(GPIO_AFSL_AFSL3 | GPIO_AFSL_AFSL5);
        GPIOB->AFS[0] |= (0UL << 12) |                                                        //PB3配置为SPI1_SCK
                                         (0UL << 20) ;                                                        //PB5配置为SPI1_MOSI
       
        SPI1_Reset();
}

 楼主 | 2015-4-16 16:06 | 显示全部楼层
本帖最后由 yuzemin1987 于 2015-4-16 16:35 编辑

示波器截图

本帖子中包含更多资源

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

x
| 2015-4-16 19:02 | 显示全部楼层
这个代码的比较详细。
| 2015-4-16 19:05 | 显示全部楼层
作为SPI总线得应用的,注意其相应的IO管脚的设置的,还一个就是时钟的选取的。
| 2015-4-17 07:57 | 显示全部楼层
GD的芯片版本不同,各种bug也不同,居然没找到勘误说明,这个问题应该新版本解决了
| 2015-4-19 19:42 | 显示全部楼层
ADC模块的中断需要写两次清除中断标志寄存器才能清除中断?这个是直接的可以从中断程序中清除掉的。
 楼主 | 2015-4-20 19:04 | 显示全部楼层
你可以写个代码测试一下
 楼主 | 2015-4-20 19:07 | 显示全部楼层
shenmu2012 发表于 2015-4-19 19:42
ADC模块的中断需要写两次清除中断标志寄存器才能清除中断?这个是直接的可以从中断程序中清除掉的。 ...

你可以写个代码测试一下
| 2015-4-20 21:04 | 显示全部楼层
AD的中断需要两次才能清除是芯片的问题?
 楼主 | 2015-4-21 14:21 | 显示全部楼层
firstblood 发表于 2015-4-20 21:04
AD的中断需要两次才能清除是芯片的问题?

那这个GD32F150C8T6芯片的AD中断应该怎么清除呢
| 2015-10-4 23:46 | 显示全部楼层
ADC1->STR &= ~(ADC_STR_STIC | ADC_STR_EOIC);放在最前面去。
| 2015-10-7 17:58 | 显示全部楼层
这些注意电阻阻抗匹配的啦。
| 2015-10-7 17:59 | 显示全部楼层
这些问题的主要在硬件方面的实现改进吧,,阻抗匹配时需要注意的。
| 2015-10-16 19:40 | 显示全部楼层
看来楼主研究的很深刻的么
| 2018-12-18 16:05 | 显示全部楼层
我是感觉150便宜  很多问题  超32K ,听一工程师说明显延时 无法使用
| 2018-12-21 08:57 | 显示全部楼层
本帖最后由 lvben5d 于 2018-12-21 08:59 编辑

关于问题3. 楼主的认真精神点赞,疑问:我记得示波器的探头并不是隔离的吧?  可以试试KEIL5仿真的时候,看下寄存器信息来验证自己想法。
| 2019-1-8 11:53 | 显示全部楼层
从道理上来说 清除一次就可以了
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式
我要创建版块 申请成为版主

论坛热帖

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