本帖最后由 jundao721 于 2017-5-16 12:26 编辑
过这一段时间的努力调试,终于实现了模拟系统,在实际的项目开发中,和单一实现某个功能不一样。单一实现某个功能还是好实现的,把很多个功能结合起来,就会发现,各种坑。虽然这个模拟系统在有限的时间内实现的功能不多,但是基本上集成了CTimer,SCTimer,AD,PWM,Oled,IIC,DCmotor等等功能。在调试的过程中,你会发现,有时候外设初始化的顺序都会影响整个系统或者影响其他功能。 这个系统主要是通过双屏显示,采集空气中的气体浓度,光亮情况,温度,气压,定时等,然后通过其他手段来调节空气的数值,比如模拟风扇来调节温度,通过模拟灯光来调节室内亮度,oled显示灯光等级等等。 下面就详细说明一下调试情况。 首先是温度和气压的采样,选择BMP180传感器,以前用过,数据还算是精准,如图1所示:
显示部分都采用的是0.96的oled显示屏,一个显示温度,气压,CH4含量,一个显示时间和亮度等级。如图2所示:
空气成分的采样,使用欧洲的一个品牌,INP20-CH4L-NCVSP,是一款CH4传感器,可以对空气中的CH4含量进行采样,因为是模拟系统,暂时仅使用1套。如图3所示:
对于温度的反馈,通过风扇改变空气流速,从而起到降压的作用,使用5V小直流作为模拟风扇,L298模块作为驱动模块。如图4所示:
室内光线控制使用光敏电阻,采样光敏电阻模块的输出电压,通过板载的led灯,改变PWM,从而改变灯光的亮度,来实现调节灯光亮度的目的。如图5所示:
时间定时,使用按键来完成时间设置定时,模拟系统里默认的是10S,使用震动电机来模拟报警,原来打算用蜂鸣器的,为了不影响群众,改为震动电机,如图6所示:
接下来聊一聊程序,把主要的部分说明一下,其他的参考附件中的main函数。 首先应该是引脚复用和GPIO初始化:如图7所示: - /* LED pins */
- IOCON_PinMuxSet(IOCON, 0, 23,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);//BMP180
- IOCON_PinMuxSet(IOCON, 0, 24,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
-
- /* Switch pins */
- IOCON_PinMuxSet(IOCON, 1, 8,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);//key
-
- IOCON_PinMuxSet(IOCON, 0, 15,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);//oled1
- IOCON_PinMuxSet(IOCON, 1, 9,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
- IOCON_PinMuxSet(IOCON, 1, 10,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
- IOCON_PinMuxSet(IOCON, 1, 11,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
-
- IOCON_PinMuxSet(IOCON, 0, 11,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);//oled2
- IOCON_PinMuxSet(IOCON, 0, 12,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
- IOCON_PinMuxSet(IOCON, 0, 13,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
- IOCON_PinMuxSet(IOCON, 0, 14,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
-
- IOCON_PinMuxSet(IOCON, 1, 1,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);//Õñ¶¯µç»ú
-
-
- IOCON_PinMuxSet(IOCON, 0, 19,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF); //motor
- IOCON_PinMuxSet(IOCON, 0, 21,IOCON_FUNC0 | IOCON_GPIO_MODE | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);
-
-
- IOCON_PinMuxSet(IOCON, 1, 4, IOCON_MODE_INACT | IOCON_FUNC0 | IOCON_ANALOG_EN | IOCON_INPFILT_OFF);//ch4AD
- IOCON_PinMuxSet(IOCON, 1, 3, IOCON_MODE_INACT | IOCON_FUNC0 | IOCON_ANALOG_EN | IOCON_INPFILT_OFF);//lightAD
-
-
- IOCON_PinMuxSet(IOCON, 0, 29, IOCON_MODE_INACT | IOCON_FUNC7 | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF);//lightpwm
- IOCON_PinMuxSet(IOCON, 1, 2, IOCON_MODE_INACT | IOCON_FUNC3 | IOCON_DIGITAL_EN | IOCON_INPFILT_OFF); //motorpwm
复制代码- /*oled2 pins blue*/
- GPIO_PinInit(GPIO,0,11,&led_config);//´Ë´¦GPIOµÄÅäÖÃÈç¹û·Å´óMotorÅäÖúóÃ棬motor²»ÄÜÔËÐÐ
- GPIO_PinInit(GPIO,0,12,&led_config);
- GPIO_PinInit(GPIO,0,13,&led_config);
- GPIO_PinInit(GPIO,0,14,&led_config);
- GPIO_SetPinsOutput(GPIO,0,1u<<11);
- GPIO_SetPinsOutput(GPIO,0,1u<<12);
- GPIO_SetPinsOutput(GPIO,0,1u<<13);
- GPIO_SetPinsOutput(GPIO,0,1u<<14);
- //
- GPIO_SetPortMask(GPIO,0,1u<<11);
- GPIO_SetPortMask(GPIO,0,1u<<12);
- GPIO_SetPortMask(GPIO,0,1u<<13);
- GPIO_SetPortMask(GPIO,0,1u<<14);
- GPIO_WriteMPort(GPIO,0,1u<<11);
- GPIO_WriteMPort(GPIO,0,1u<<12);
- GPIO_WriteMPort(GPIO,0,1u<<13);
- GPIO_WriteMPort(GPIO,0,1u<<14);
复制代码
然后是按键初始化和按键处理,如图8和图9所示所示: - INPUTMUX_Init(INPUTMUX);
- INPUTMUX_AttachSignal(INPUTMUX,kPINT_PinInt0,kINPUTMUX_GpioPort1Pin8ToPintsel);
- /* Turnoff clock to inputmux to save power. Clock is only needed to make changes */
- INPUTMUX_Deinit(INPUTMUX);
- /* Initialize PINT */
- PINT_Init(PINT);
- /* Setup Pin Interrupt 0 for rising edge */
- PINT_PinInterruptConfig(PINT, kPINT_PinInt0, kPINT_PinIntEnableFallEdge, pint_intr_callback);
-
- /* Enable callbacks for PINT */
- PINT_EnableCallback(PINT);
复制代码- void Key_process(void)
- {
- uint8_t i;
- if(keyflag==1)
- {
- CTIMER_StartTimer(CTIMER1);
- keyflag=0;
- }
- if(Tfinishflag ==1)
- {
- CTIMER_StopTimer(CTIMER1);
- GPIO_SetPinsOutput(GPIO,1,1u<<1);//Õñ¶¯µç»ú
- for(i=0;i<5;i++)
- Delay_nms(0xAFFFF);
- GPIO_ClearPinsOutput(GPIO,1,1u<<1);
- Tfinishflag=0;
- }
- }
复制代码
然后是定时器1计数中断初始化,如图10所示: - void Key_TimConfig(void)//¶¨Ê±Æ÷1ÓÃÓÚ¼ÆÊý
- {
- ctimer_config_t config;
- static ctimer_match_config_t matchConfig0;
- SYSCON->ASYNCAPBCTRL = 1;
- CLOCK_AttachClk(kFRO12M_to_ASYNC_APB);
- CTIMER_GetDefaultConfig(&config);
- CTIMER_Init(CTIMER1,&config);
-
- //match channel 0 configuration
- matchConfig0.enableCounterReset = true;
- matchConfig0.enableCounterStop = false;
- matchConfig0.matchValue = CLOCK_GetFreq(kCLOCK_BusClk);//1S
- matchConfig0.outControl = kCTIMER_Output_Toggle;
- matchConfig0.outPinInitState = false;
- matchConfig0.enableInterrupt = true;
-
- CTIMER_RegisterCallBack(CTIMER1,&ctimer_callback_table[0],kCTIMER_MultipleCallback);
- CTIMER_SetupMatch(CTIMER1,kCTIMER_Match_0,&matchConfig0);
- // CTIMER_StartTimer(CTIMER1);
- CTIMER_StopTimer(CTIMER1);
- }
复制代码
然后就是BMP180的显示程序: - BMP085Convert();
- for(t=0;t<10;t++)
- Delay_nms(0xAFFFF);
- lcdshow[0] =(u8) (temper/100);
- lcdshow[1] =(u8) ((temper-(temper/100)*100)/10);
- lcdshow[2] =(u8) (temper%10);
- sprintf(lcdtest,"%d",lcdshow[0]);
- sprintf(lcdtest2,"%d",lcdshow[1]);
- sprintf(lcdtest3,"%d",lcdshow[2]);
- LCD_Print(40,0,lcdtest,TYPE16X16,TYPE8X16);
- LCD_Print(48,0,lcdtest2,TYPE16X16,TYPE8X16);
- LCD_Print(56,0,lcdpoint,TYPE16X16,TYPE8X16);
- LCD_Print(64,0,lcdtest3,TYPE16X16,TYPE8X16);
- LCD_Print(72,0,lcdword4,TYPE16X16,TYPE8X16);
复制代码
其实oled显示都一样,都不多说了,下面是多路采样AD的初始化: - /* Configure the converter. */
- adcConfigStruct.clockMode = kADC_ClockSynchronousMode; /* Using sync clock source. */
- adcConfigStruct.clockDividerNumber = 1; /* The divider for sync clock is 2. */
- adcConfigStruct.resolution = kADC_Resolution12bit;
- adcConfigStruct.enableBypassCalibration = false;
- adcConfigStruct.sampleTimeNumber = 0U;
- ADC_Init(ADC0, &adcConfigStruct);
- /* Use the temperature sensor input to channel 0. */
- // ADC_EnableTemperatureSensor(ADC0, false);
- /* Enable channel 7's conversion in Sequence A. */
- adcConvSeqConfigStruct.channelMask = (1U << 7)|(1U << 6); /* Includes channel 0. */
- adcConvSeqConfigStruct.triggerMask = 0U;
- adcConvSeqConfigStruct.triggerPolarity = kADC_TriggerPolarityNegativeEdge;
- adcConvSeqConfigStruct.enableSingleStep = false;
- adcConvSeqConfigStruct.enableSyncBypass = false;
- adcConvSeqConfigStruct.interruptMode = kADC_InterruptForEachSequence;
- ADC_SetConvSeqAConfig(ADC0, &adcConvSeqConfigStruct);
- ADC_EnableConvSeqA(ADC0, true); /* Enable the conversion sequence A. */
复制代码
然后是光敏电阻改变led的亮度处理: - ctimer_config_t config;
- // uint32_t LightsrcClock_Hz;
- SYSCON->ASYNCAPBCTRL = 1;
- /* CTimer0 counter uses the AHB clock, some CTimer1 modules use the Aysnc clock */
- LightsrcClock_Hz = CLOCK_GetFreq(kCLOCK_BusClk);
- CTIMER_GetDefaultConfig(&config);
- CTIMER_Init(CTIMER0, &config);
- // CTIMER_SetupPwm(CTIMER0, kCTIMER_Match_1, 90, 1000, srcClock_Hz, false);
- CTIMER_StartTimer(CTIMER0);
复制代码- if(ADLightResult <=0x100)//Êý¾Ý´¦Àí²¿·Ö±ØÐëÔÚADת»»Ç°Ãæ
- {
- CTIMER_SetupPwm(CTIMER0, kCTIMER_Match_1, 100, 1000, LightsrcClock_Hz, false);
- // Delay_nms(1000);
- DLight =1;
- }
- else if((ADLightResult>0x100) && (ADLightResult<=0x300))
- {
- CTIMER_SetupPwm(CTIMER0, kCTIMER_Match_1,96, 1000, LightsrcClock_Hz, false);
- // Delay_nms(1000);
- DLight =2;
- }
- else if((ADLightResult>0x300)&&(ADLightResult<=0x500))
- {
- CTIMER_SetupPwm(CTIMER0, kCTIMER_Match_1, 90, 1000, LightsrcClock_Hz, false);
- // Delay_nms(1000);
- DLight =3;
- }
复制代码
模拟风扇电机定时器初始化: - sctimer_config_t sconfig;
- sctimer_pwm_signal_param_t pwmParam;
- uint32_t srctClock_Hz;
-
- srctClock_Hz = CLOCK_GetFreq(kCLOCK_BusClk);
- SCTIMER_GetDefaultConfig(&sconfig);
- SCTIMER_Init(SCT0, &sconfig);
- /* Configure PWM params with frequency 24kHZ from output 4 */
- pwmParam.output = kSCTIMER_Out_5;
- pwmParam.level = kSCTIMER_HighTrue;
- pwmParam.dutyCyclePercent = 18u;//updatedDutycycle;
- SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, 1000U, srctClock_Hz, &eventNumberOutput5);
复制代码
以上都是部分重要的程序,其他的可参考附件。 最后是整个系统的操作视频,优酷正在审查: 按动按键观察定时时间变化,10S震动电机报警;改变灯光亮度,观察led5(绿灯)亮度变化和oled中光线等级的变化;用手摸温度传感器,改变温度,设置为大于31.5度风扇转动,观察温度数值变化和风扇的反馈情况。
|