[创新制造展示]

【21ic第三届设计大赛】+冗余执行系统(STM32+阿里云)

[复制链接]
4067|43
手机看帖
扫描二维码
随时随地手机跟帖
奋斗小范|  楼主 | 2019-6-5 16:08 | 显示全部楼层 |阅读模式
本帖最后由 奋斗小范 于 2019-7-4 18:07 编辑

  偶然间从朋友那听说了论坛上正在举行第三届设计大赛,决定参加一下,让我那一堆“尘封已久”的开发板“重见天日”,因为之前使用STM32F4系列做过简易示波器与信号发生器,并且相关制作教程也较多,因此选取主题B作为此次参赛题目。

首先,从我百宝箱里翻出此次比赛需要的硬件
STM32F103ZET6开发板*1,
STM32F103C8T6最小系统板*1,
4.3寸TFTLCD触摸屏*1,
WiFi模组
电位器*1,
USB转TTL*1,
继电器*1,
绿色LED*1,
电阻、线材若干
WiFi模组(对接阿里云用)。
ZI(@{A44LN$D4]14L0_NMR0.png

先贴部分硬件图片:
1.png


关于此次设计我将分为五部分进行:
1)项目方案的构想;
2)设计、搭建;
3)调试流程;
4)制作心得和总结;
5)视频展示。



使用特权

评论回复
评论
21ic小喇叭 2019-6-6 13:48 回复TA
期待 
21ic小喇叭 2019-6-6 13:48 回复TA
期待 

相关帖子

奋斗小范|  楼主 | 2019-6-5 16:14 | 显示全部楼层
本帖最后由 奋斗小范 于 2019-6-26 19:16 编辑

1)项目方案的构想;
①审题
此题目分为两个项目 :基础项目与加分项目。
基础项目为完成主要的控制功能,AD采样数值分为三档,与LED三种状态相对应(灭, 3Hz闪烁, 常亮),并显示AD读数与LED状态。
加分项目为冗余控制功能,当主控制器失效或异常时,从控制器能检测到主控制器异常,断开主控电源,并接管LED控制。
②构想
既然是冗余执行系统,可靠性是重中之重,因此两控制器运作必须是相互独立,互不干扰,因此排除通过通讯的方式进行控制器之间的协调。
本次设计采用双控制器独立运行的方式,
主要思路是:
主控制器通过ADC获取电位器当前状态,通过定时器控制LED闪烁,并将AD值跟LED状态显示在触摸屏上。
11.jpg
从控制器在主控制器功能基础上,增加监测功能,监测主控制器输出,在主控制器控制异常时,断开主控制器电源并接管控制,另外从控制器AD值、LED状态与主控制器状态通过串口或者其他方式上传到PC上。
222.jpg

二次更改:
系统对接至阿里云,可以通过APP显示AD值、LED状态与主控制器状态等信息,并可以通过APP控制系统动作。

使用特权

评论回复
评论
zhanzr21 2019-6-5 19:13 回复TA
独立工作的思路很赞, 期待后续资料! 
奋斗小范|  楼主 | 2019-6-6 08:46 | 显示全部楼层
本帖最后由 奋斗小范 于 2019-6-26 19:19 编辑

2)设计、搭建:

①搭建硬件平台。
因为本次用到的硬件均为现成模块,本次就不再做PCB。
系统示意图:
框图.jpg

搭建完成:
ps:从控制器线没连。。。
IMG_20190604_163755.jpg

②搭建软件框架。
因功能较为简单,没有过多考虑节约资源。

主控制器资源使用情况:
USART1    打印调试信息
FSMC     LCD
ADC1-CH1  电位器电压
TIM3     LED 3Hz闪烁
SPI     外部flash(存字库)
SDIO     SD卡(刷字库以及其他文件)

从控制器资源使用情况:USART1    打印调试信息
USART3    备用(后期可能加其他功能)   
ADC1-CH1  电位器电压
TIM3     定时检测主控制器状态
TIM4     LED 3Hz闪烁

更改:
从控制器USART3,改为与WiFi模组通讯。

使用特权

评论回复
515192147| | 2019-6-7 09:37 | 显示全部楼层
是 类似  这个 图的 功能吗 canweb001.JPG
我们 有 现成的 开发板,一个 MST 可带 99个开发板从站,
很简单就可以与 腾讯云服务器 交换数据
kfb001.JPG

使用特权

评论回复
奋斗小范|  楼主 | 2019-6-7 10:53 | 显示全部楼层
515192147 发表于 2019-6-7 09:37
是 类似  这个 图的 功能吗
我们 有 现成的 开发板,一个 MST 可带 99个开发板从站,
很简单就可以与 腾讯 ...

不是的,不过感谢你提醒了我,搞完所要求的功能以后,考虑接入云。

使用特权

评论回复
奋斗小范|  楼主 | 2019-6-7 17:17 | 显示全部楼层
本帖最后由 奋斗小范 于 2019-6-19 10:53 编辑

3)调试流程:
①主控制器:
工程图片:
%QRLMY3IXHBV@J2XYP3M}7W.png

初始化
delay_init();  
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
LED_Init();
KEY_Init();
LCD_Init();
Adc_Init();
TIM3_Init(1666,7199);
W25QXX_Init();//初始化W25Q128
my_mem_init(SRAMIN);//初始化内部内存池
exfuns_init();//为fatfs相关变量申请内存  
f_mount(fs[0],"0:",1);//挂载SD卡
f_mount(fs[1],"1:",1);//挂载FLASH.
LCD_Display_Dir(1);

主控制器LCD显示(显示简单的做了一下,另外照片画质太差请见谅

ADC采样值左侧显示,并以图形显示当前所处档位。
LED状态右侧显示,LED灭右侧框内为白色,LED闪烁框内会有绿色方块闪烁,LED常亮对应位置绿色方块常亮。
QQ图片20190607164107.png

无法显示汉字,增加字库之后:
IRLEB8HZS_2OCAKN`2G5@1N.png

ADC初始化:
void  Adc_Init(void)
{         
        ADC_InitTypeDef ADC_InitStructure;
        GPIO_InitTypeDef GPIO_InitStructure;

        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_ADC1        , ENABLE );          //使能ADC1通道时钟

        RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                //模拟输入引脚
        GPIO_Init(GPIOA, &GPIO_InitStructure);        

        ADC_DeInit(ADC1);  //复位ADC1,将外设 ADC1 的全部寄存器重设为缺省值

        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;        //ADC工作模式:ADC1和ADC2工作在独立模式
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;        //模数转换工作在单通道模式
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;        //模数转换工作在单次转换模式
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //转换由软件而不是外部触发启动
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;        //ADC数据右对齐
        ADC_InitStructure.ADC_NbrOfChannel = 1;        //顺序进行规则转换的ADC通道的数目
        ADC_Init(ADC1, &ADC_InitStructure);        //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   
  
        ADC_Cmd(ADC1, ENABLE);        //使能指定的ADC1
        ADC_ResetCalibration(ADC1);        //使能复位校准  
        while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束
        ADC_StartCalibration(ADC1);         //开启AD校准
        while(ADC_GetCalibrationStatus(ADC1));         //等待校准结束
//        ADC_SoftwareStartConvCmd(ADC1, ENABLE);                //使能指定的ADC1的软件转换启动功能
}
直接在主函数中循环读取AD值:
Adc_Val=Get_Adc_Average(ADC_Channel_1,100);
将AD值显示在LCD上,并计算出相应的长度,以图形显示在屏幕上:
LCD_ShowxNum(150,140,Adc_Val,4,24,0);//显示ADC的值
Adc_X = 1.0*261 * Adc_Val / 4095;
LCD_Fill(82,212,82+Adc_X,338,GREEN);
LCD_Fill(82+Adc_X,212,343,338,WHITE);

定时器初始化:
因此设计对时间要求不高,刷屏直接放在中断中进行。
void TIM3_Init(void)
{
        TIM_TimeBaseInitTypeDef        TIM_TimeBaseStructure;
        NVIC_InitTypeDef        NVIC_InitStructure;
        
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
        
        TIM_TimeBaseStructure.TIM_Period = 1666;
        TIM_TimeBaseStructure.TIM_Prescaler =7199;
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
        TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );

        NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

        TIM_Cmd(TIM3, DISABLE);
}
通过AD采样值控制LED状态:
if(Adc_Val<1365)
{
    TIM_Cmd(TIM3, DISABLE);
    LED2=1;
    LCD_Fill(502,177,673,353,WHITE);
}
else if(Adc_Val<2730)
{
    TIM_Cmd(TIM3, ENABLE);
}
else
{
    TIM_Cmd(TIM3, DISABLE);
    LED2=0;
    LCD_Fill(502,177,673,353,GREEN);
}
LCD初始化及驱动代码:
//LCD的画笔颜色和背景色           
u16 POINT_COLOR=0x0000;        //画笔颜色
u16 BACK_COLOR=0xFFFF;  //背景色
  
//管理LCD重要参数
//默认为竖屏
_lcd_dev lcddev;
         
//写寄存器函数
//regval:寄存器值
void LCD_WR_REG(u16 regval)
{   
        LCD->LCD_REG=regval;//写入要写的寄存器序号         
}
//写LCD数据
//data:要写入的值
void LCD_WR_DATA(u16 data)
{         
        LCD->LCD_RAM=data;                 
}
//读LCD数据
//返回值:读到的值
u16 LCD_RD_DATA(void)
{
        vu16 ram;                        //防止被优化
        ram=LCD->LCD_RAM;       
        return ram;         
}                                          
//写寄存器
//LCD_Reg:寄存器地址
//LCD_RegValue:要写入的数据
void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue)
{       
        LCD->LCD_REG = LCD_Reg;
        LCD->LCD_RAM = LCD_RegValue;         
}          
//读寄存器
//LCD_Reg:寄存器地址
//返回值:读到的数据
u16 LCD_ReadReg(u16 LCD_Reg)
{                                                                                  
        LCD_WR_REG(LCD_Reg);
        delay_us(5);                  
        return LCD_RD_DATA();
}   
//开始写GRAM
void LCD_WriteRAM_Prepare(void)
{
        LCD->LCD_REG=lcddev.wramcmd;          
}         
//LCD写GRAM
//RGB_Code:颜色值
void LCD_WriteRAM(u16 RGB_Code)
{                                                            
        LCD->LCD_RAM = RGB_Code;//写十六位GRAM
}
//从ILI93xx读出的数据为GBR格式,而我们写入的时候为RGB格式。
//通过该函数转换
//c:GBR格式的颜色值
//返回值:RGB格式的颜色值
u16 LCD_BGR2RGB(u16 c)
{
        u16  r,g,b,rgb;   
        b=(c>>0)&0x1f;
        g=(c>>5)&0x3f;
        r=(c>>11)&0x1f;         
        rgb=(b<<11)+(g<<5)+(r<<0);                 
        return(rgb);
}
//当mdk -O1时间优化时需要设置
//延时i
void opt_delay(u8 i)
{
        while(i--);
}
//读取个某点的颜色值         
//x,y:坐标
//返回值:此点的颜色
u16 LCD_ReadPoint(u16 x,u16 y)
{
        u16 r=0,g=0,b=0;
        if(x>=lcddev.width||y>=lcddev.height)
                return 0;
        LCD_SetCursor(x,y);            
        LCD_WR_REG(0X2E);

        r=LCD_RD_DATA();
        opt_delay(2);          
        r=LCD_RD_DATA();

        opt_delay(2);          
        b=LCD_RD_DATA();
        g=r&0XFF;
        g<<=8;

        return (((r>>11)<<11)|((g>>10)<<5)|(b>>11));
}                         
//LCD开启显示
void LCD_DisplayOn(void)
{                                          
        LCD_WR_REG(0X29);
}         
//LCD关闭显示
void LCD_DisplayOff(void)
{          
        LCD_WR_REG(0X28);
}   
//设置光标位置
//Xpos:横坐标
//Ypos:纵坐标
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{         
        LCD_WR_REG(lcddev.setxcmd);
        LCD_WR_DATA(Xpos>>8);
        LCD_WR_DATA(Xpos&0XFF);                          
        LCD_WR_REG(lcddev.setycmd);
        LCD_WR_DATA(Ypos>>8);
        LCD_WR_DATA(Ypos&0XFF);                

}                  
//设置LCD的自动扫描方向           
void LCD_Scan_Dir(u8 dir)
{
        u16 regval=0;
        u16 dirreg=0;
        u16 temp;  
        switch(dir)
        {
                case L2R_U2D://从左到右,从上到下
                        regval|=(0<<7)|(0<<6)|(0<<5);
                        break;
                case L2R_D2U://从左到右,从下到上
                        regval|=(1<<7)|(0<<6)|(0<<5);
                        break;
                case R2L_U2D://从右到左,从上到下
                        regval|=(0<<7)|(1<<6)|(0<<5);
                        break;
                case R2L_D2U://从右到左,从下到上
                        regval|=(1<<7)|(1<<6)|(0<<5);
                        break;         
                case U2D_L2R://从上到下,从左到右
                        regval|=(0<<7)|(0<<6)|(1<<5);
                        break;
                case U2D_R2L://从上到下,从右到左
                        regval|=(0<<7)|(1<<6)|(1<<5);
                        break;
                case D2U_L2R://从下到上,从左到右
                        regval|=(1<<7)|(0<<6)|(1<<5);
                        break;
                case D2U_R2L://从下到上,从右到左
                        regval|=(1<<7)|(1<<6)|(1<<5);
                        break;         
        }
        dirreg=0X36;
        LCD_WriteReg(dirreg,regval);

        if(regval&0X20)
        {
                if(lcddev.width<lcddev.height)//交换X,Y
                {
                        temp=lcddev.width;
                        lcddev.width=lcddev.height;
                        lcddev.height=temp;
                }
        }
        else  
        {
                if(lcddev.width>lcddev.height)//交换X,Y
                {
                        temp=lcddev.width;
                        lcddev.width=lcddev.height;
                        lcddev.height=temp;
                }
        }  
        LCD_WR_REG(lcddev.setxcmd);
        LCD_WR_DATA(0);LCD_WR_DATA(0);
        LCD_WR_DATA((lcddev.width-1)>>8);
        LCD_WR_DATA((lcddev.width-1)&0XFF);
        LCD_WR_REG(lcddev.setycmd);
        LCD_WR_DATA(0);LCD_WR_DATA(0);
        LCD_WR_DATA((lcddev.height-1)>>8);
        LCD_WR_DATA((lcddev.height-1)&0XFF);  
}     
//画点
//x,y:坐标
//POINT_COLOR:此点的颜色
void LCD_DrawPoint(u16 x,u16 y)
{
        LCD_SetCursor(x,y);
        LCD_WriteRAM_Prepare();
        LCD->LCD_RAM=POINT_COLOR;
}
//快速画点
//x,y:坐标
//color:颜色
void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color)
{          

        LCD_WR_REG(lcddev.setxcmd);
        LCD_WR_DATA(x>>8);
        LCD_WR_DATA(x&0XFF);
        LCD_WR_REG(lcddev.setycmd);
        LCD_WR_DATA(y>>8);
        LCD_WR_DATA(y&0XFF);

        LCD->LCD_REG=lcddev.wramcmd;
        LCD->LCD_RAM=color;
}         
//SSD1963 背光设置
//pwm:背光等级,0~100.越大越亮.
void LCD_SSD_BackLightSet(u8 pwm)
{       
        LCD_WR_REG(0xBE);        //配置PWM输出
        LCD_WR_DATA(0x05);        //1设置PWM频率
        LCD_WR_DATA(pwm*2.55);//2设置PWM占空比
        LCD_WR_DATA(0x01);        //3设置C
        LCD_WR_DATA(0xFF);        //4设置D
        LCD_WR_DATA(0x00);        //5设置E
        LCD_WR_DATA(0x00);        //6设置F
}

//设置LCD显示方向
//dir:0,竖屏;1,横屏
void LCD_Display_Dir(u8 dir)
{
        if(dir==0)                        //竖屏
        {
                lcddev.dir=0;        //竖屏
                lcddev.width=240;
                lcddev.height=320;
                lcddev.wramcmd=0X2C;
                lcddev.setxcmd=0X2A;
                lcddev.setycmd=0X2B;           

        }
        else                                 //横屏
        {                                         
                lcddev.dir=1;
                lcddev.width=320;
                lcddev.height=240;
                lcddev.wramcmd=0X2C;
                lcddev.setxcmd=0X2A;
                lcddev.setycmd=0X2B;           
        }
        LCD_Scan_Dir(DFT_SCAN_DIR);        //默认扫描方向
}         
//设置窗口,并自动设置画点坐标到窗口左上角(sx,sy).
//sx,sy:窗口起始坐标(左上角)
//width,height:窗口宽度和高度,必须大于0!!
//窗体大小:width*height.
void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height)
{   
        u8 hsareg,heareg,vsareg,veareg;
        u16 hsaval,heaval,vsaval,veaval;
        u16 twidth,theight;
        twidth=sx+width-1;
        theight=sy+height-1;
        LCD_WR_REG(lcddev.setxcmd);
        LCD_WR_DATA(sx>>8);
        LCD_WR_DATA(sx&0XFF);         
        LCD_WR_DATA(twidth>>8);
        LCD_WR_DATA(twidth&0XFF);  
        LCD_WR_REG(lcddev.setycmd);
        LCD_WR_DATA(sy>>8);
        LCD_WR_DATA(sy&0XFF);
        LCD_WR_DATA(theight>>8);
        LCD_WR_DATA(theight&0XFF);
}
//初始化lcd
//该初始化函数可以初始化各种ILI93XX液晶,但是其他函数是基于ILI9320的!!!
//在其他型号的驱动芯片上没有测试!
void LCD_Init(void)
{                                        
        GPIO_InitTypeDef GPIO_InitStructure;
        FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
  FSMC_NORSRAMTimingInitTypeDef  readWriteTiming;
        FSMC_NORSRAMTimingInitTypeDef  writeTiming;
       
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE);        //使能FSMC时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOG,ENABLE);//使能PORTB,D,E,G以及AFIO复用功能时钟


        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                                 //PB0 推挽输出 背光
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
       
        //PORTD复用推挽输出  
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_14|GPIO_Pin_15;                                 //        //PORTD复用推挽输出  
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                  //复用推挽输出   
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOD, &GPIO_InitStructure);
           
        //PORTE复用推挽输出  
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;                                 //        //PORTD复用推挽输出  
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                  //复用推挽输出   
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOE, &GPIO_InitStructure);                                                                                                                  

           //        //PORTG12复用推挽输出 A0       
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_12;         //        //PORTD复用推挽输出  
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                  //复用推挽输出   
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOG, &GPIO_InitStructure);

        readWriteTiming.FSMC_AddressSetupTime = 0x01;         //地址建立时间(ADDSET)为2个HCLK 1/36M=27ns
  readWriteTiming.FSMC_AddressHoldTime = 0x00;         //地址保持时间(ADDHLD)模式A未用到       
  readWriteTiming.FSMC_DataSetupTime = 0x0f;                 // 数据保存时间为16个HCLK,因为液晶驱动IC的读数据的时候,速度不能太快,尤其对1289这个IC。
  readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
  readWriteTiming.FSMC_CLKDivision = 0x00;
  readWriteTiming.FSMC_DataLatency = 0x00;
  readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A;         //模式A
   

        writeTiming.FSMC_AddressSetupTime = 0x00;         //地址建立时间(ADDSET)为1个HCLK  
  writeTiming.FSMC_AddressHoldTime = 0x00;         //地址保持时间(A               
  writeTiming.FSMC_DataSetupTime = 0x03;                 ////数据保存时间为4个HCLK       
  writeTiming.FSMC_BusTurnAroundDuration = 0x00;
  writeTiming.FSMC_CLKDivision = 0x00;
  writeTiming.FSMC_DataLatency = 0x00;
  writeTiming.FSMC_AccessMode = FSMC_AccessMode_A;         //模式A


  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;//  这里我们使用NE4 ,也就对应BTCR[6],[7]。
  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; // 不复用数据地址
  FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM;  //SRAM   
  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//存储器数据宽度为16bit   
  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;// FSMC_BurstAccessMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
        FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;   
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;  
  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;        //  存储器写使能
  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;   
  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable; // 读写使用不同的时序
  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; //读写时序
  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &writeTiming;  //写时序

  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);  //初始化FSMC配置

        FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);  // 使能BANK1
       
        delay_ms(50);                                         // delay 50 ms

        LCD_WR_REG(0xCF);  
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0xC1);
        LCD_WR_DATA(0X30);
        LCD_WR_REG(0xED);  
        LCD_WR_DATA(0x64);
        LCD_WR_DATA(0x03);
        LCD_WR_DATA(0X12);
        LCD_WR_DATA(0X81);
        LCD_WR_REG(0xE8);  
        LCD_WR_DATA(0x85);
        LCD_WR_DATA(0x10);
        LCD_WR_DATA(0x7A);
        LCD_WR_REG(0xCB);  
        LCD_WR_DATA(0x39);
        LCD_WR_DATA(0x2C);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x34);
        LCD_WR_DATA(0x02);
        LCD_WR_REG(0xF7);  
        LCD_WR_DATA(0x20);
        LCD_WR_REG(0xEA);  
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_REG(0xC0);    //Power control
        LCD_WR_DATA(0x1B);   //VRH[5:0]
        LCD_WR_REG(0xC1);    //Power control
        LCD_WR_DATA(0x01);   //SAP[2:0];BT[3:0]
        LCD_WR_REG(0xC5);    //VCM control
        LCD_WR_DATA(0x30);          //3F
        LCD_WR_DATA(0x30);          //3C
        LCD_WR_REG(0xC7);    //VCM control2
        LCD_WR_DATA(0XB7);
        LCD_WR_REG(0x36);    // Memory Access Control
        LCD_WR_DATA(0x48);
        LCD_WR_REG(0x3A);   
        LCD_WR_DATA(0x55);
        LCD_WR_REG(0xB1);   
        LCD_WR_DATA(0x00);   
        LCD_WR_DATA(0x1A);
        LCD_WR_REG(0xB6);    // Display Function Control
        LCD_WR_DATA(0x0A);
        LCD_WR_DATA(0xA2);
        LCD_WR_REG(0xF2);    // 3Gamma Function Disable
        LCD_WR_DATA(0x00);
        LCD_WR_REG(0x26);    //Gamma curve selected
        LCD_WR_DATA(0x01);
        LCD_WR_REG(0xE0);    //Set Gamma
        LCD_WR_DATA(0x0F);
        LCD_WR_DATA(0x2A);
        LCD_WR_DATA(0x28);
        LCD_WR_DATA(0x08);
        LCD_WR_DATA(0x0E);
        LCD_WR_DATA(0x08);
        LCD_WR_DATA(0x54);
        LCD_WR_DATA(0XA9);
        LCD_WR_DATA(0x43);
        LCD_WR_DATA(0x0A);
        LCD_WR_DATA(0x0F);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);                  
        LCD_WR_REG(0XE1);    //Set Gamma
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x15);
        LCD_WR_DATA(0x17);
        LCD_WR_DATA(0x07);
        LCD_WR_DATA(0x11);
        LCD_WR_DATA(0x06);
        LCD_WR_DATA(0x2B);
        LCD_WR_DATA(0x56);
        LCD_WR_DATA(0x3C);
        LCD_WR_DATA(0x05);
        LCD_WR_DATA(0x10);
        LCD_WR_DATA(0x0F);
        LCD_WR_DATA(0x3F);
        LCD_WR_DATA(0x3F);
        LCD_WR_DATA(0x0F);
        LCD_WR_REG(0x2B);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x01);
        LCD_WR_DATA(0x3f);
        LCD_WR_REG(0x2A);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0x00);
        LCD_WR_DATA(0xef);         
        LCD_WR_REG(0x11); //Exit Sleep
        delay_ms(120);
        LCD_WR_REG(0x29); //display on       
       
        LCD_Display_Dir(0);                //默认为竖屏
        LCD_LED=1;                                //点亮背光
        LCD_Clear(WHITE);
}  
//清屏函数
//color:要清屏的填充色
void LCD_Clear(u16 color)
{
        u32 index=0;      
        u32 totalpoint=lcddev.width;
        totalpoint*=lcddev.height;                         //得到总点数
        if((lcddev.id==0X6804)&&(lcddev.dir==1))//6804横屏的时候特殊处理  
        {                                                    
                lcddev.dir=0;         
                lcddev.setxcmd=0X2A;
                lcddev.setycmd=0X2B;                                  
                LCD_SetCursor(0x00,0x0000);                //设置光标位置  
                lcddev.dir=1;         
          lcddev.setxcmd=0X2B;
                lcddev.setycmd=0X2A;           
        }
        else
                LCD_SetCursor(0x00,0x0000);        //设置光标位置
        LCD_WriteRAM_Prepare();                     //开始写入GRAM                   
        for(index=0;index<totalpoint;index++)
        {
                LCD->LCD_RAM=color;       
        }
}  
//在指定区域内填充单个颜色
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)   
//color:要填充的颜色
void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
{         
        u16 i,j;
        u16 xlen=0;
        u16 temp;

        xlen=ex-sx+1;         
        for(i=sy;i<=ey;i++)
        {
                LCD_SetCursor(sx,i);                                      //设置光标位置
                LCD_WriteRAM_Prepare();                             //开始写入GRAM          
                for(j=0;j<xlen;j++)
                        LCD->LCD_RAM=color;        //显示颜色             
        }

}  
//在指定区域内填充指定颜色块                         
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)   
//color:要填充的颜色
void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
{  
        u16 height,width;
        u16 i,j;
        width=ex-sx+1;                         //得到填充的宽度
        height=ey-sy+1;                        //高度
        for(i=0;i<height;i++)
        {
                LCD_SetCursor(sx,sy+i);           //设置光标位置
                LCD_WriteRAM_Prepare();     //开始写入GRAM
                for(j=0;j<width;j++)
                        LCD->LCD_RAM=color[i*width+j];//写入数据
        }                  
}  
//画线
//x1,y1:起点坐标
//x2,y2:终点坐标  
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
{
        u16 t;
        int xerr=0,yerr=0,delta_x,delta_y,distance;
        int incx,incy,uRow,uCol;
        delta_x=x2-x1; //计算坐标增量
        delta_y=y2-y1;
        uRow=x1;
        uCol=y1;
        if(delta_x>0)
                incx=1; //设置单步方向
        else if(delta_x==0)
                incx=0;//垂直线
        else
        {
                incx=-1;
                delta_x=-delta_x;
        }
        if(delta_y>0)
                incy=1;
        else if(delta_y==0)
                incy=0;//水平线
        else
        {
                incy=-1;
                delta_y=-delta_y;
        }
        if( delta_x>delta_y)
                distance=delta_x; //选取基本增量坐标轴
        else
                distance=delta_y;
        for(t=0;t<=distance+1;t++ )//画线输出
        {
                LCD_DrawPoint(uRow,uCol);//画点
                xerr+=delta_x ;
                yerr+=delta_y ;
                if(xerr>distance)
                {
                        xerr-=distance;
                        uRow+=incx;
                }
                if(yerr>distance)
                {
                        yerr-=distance;
                        uCol+=incy;
                }
        }  
}   
//画矩形          
//(x1,y1),(x2,y2):矩形的对角坐标
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)
{
        LCD_DrawLine(x1,y1,x2,y1);
        LCD_DrawLine(x1,y1,x1,y2);
        LCD_DrawLine(x1,y2,x2,y2);
        LCD_DrawLine(x2,y1,x2,y2);
}
//在指定位置画一个指定大小的圆
//(x,y):中心点
//r    :半径
void LCD_Draw_Circle(u16 x0,u16 y0,u8 r)
{
        int a,b;
        int di;
        a=0;b=r;          
        di=3-(r<<1);             //判断下个点位置的标志
        while(a<=b)
        {
                LCD_DrawPoint(x0+a,y0-b);             //5
                LCD_DrawPoint(x0+b,y0-a);             //0           
                LCD_DrawPoint(x0+b,y0+a);             //4               
                LCD_DrawPoint(x0+a,y0+b);             //6
                LCD_DrawPoint(x0-a,y0+b);             //1      
                LCD_DrawPoint(x0-b,y0+a);            
                LCD_DrawPoint(x0-a,y0-b);             //2            
          LCD_DrawPoint(x0-b,y0-a);             //7                     
                a++;
                //使用Bresenham算法画圆     
                if(di<0)
                        di +=4*a+6;          
                else
                {
                        di+=10+4*(a-b);   
                        b--;
                }                                                     
        }
}                                                                           
//在指定位置显示一个字符
//x,y:起始坐标
//num:要显示的字符:" "--->"~"
//size:字体大小 12/16/24
//mode:叠加方式(1)还是非叠加方式(0)
void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)
{                                                            
  u8 temp,t1,t;
        u16 y0=y;
        u8 csize=(size/8+((size%8)?1:0))*(size/2);                //得到字体一个字符对应点阵集所占的字节数       
        num=num-' ';//得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)
        for(t=0;t<csize;t++)
        {   
                if(size==12)
                        temp=asc2_1206[num][t];                  //调用1206字体
                else if(size==16)
                        temp=asc2_1608[num][t];        //调用1608字体
                else if(size==24)
                        temp=asc2_2412[num][t];        //调用2412字体
                else
                        return;                                                                //没有的字库
                for(t1=0;t1<8;t1++)
                {                            
                        if(temp&0x80)
                                LCD_Fast_DrawPoint(x,y,POINT_COLOR);
                        else if(mode==0)
                                LCD_Fast_DrawPoint(x,y,BACK_COLOR);
                        temp<<=1;
                        y++;
                        if(y>=lcddev.height)
                                return;                //超区域了
                        if((y-y0)==size)
                        {
                                y=y0;
                                x++;
                                if(x>=lcddev.width)
                                        return;        //超区域了
                                break;
                        }
                }           
        }                                            
}   
//m^n函数
//返回值:m^n次方.
u32 LCD_Pow(u8 m,u8 n)
{
        u32 result=1;         
        while(n--)
                result*=m;   
        return result;
}                         
//显示数字,高位为0,则不显示
//x,y :起点坐标         
//len :数字的位数
//size:字体大小
//color:颜色
//num:数值(0~4294967295);         
void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)
{                
        u8 t,temp;
        u8 enshow=0;                                                  
        for(t=0;t<len;t++)
        {
                temp=(num/LCD_Pow(10,len-t-1))%10;
                if(enshow==0&&t<(len-1))
                {
                        if(temp==0)
                        {
                                LCD_ShowChar(x+(size/2)*t,y,' ',size,0);
                                continue;
                        }
                        else
                                enshow=1;
                          
                }
                 LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,0);
        }
}
//显示数字,高位为0,还是显示
//x,y:起点坐标
//num:数值(0~999999999);         
//len:长度(即要显示的位数)
//size:字体大小
//mode:
//[7]:0,不填充;1,填充0.
//[6:1]:保留
//[0]:0,非叠加显示;1,叠加显示.
void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)
{  
        u8 t,temp;
        u8 enshow=0;                                                  
        for(t=0;t<len;t++)
        {
                temp=(num/LCD_Pow(10,len-t-1))%10;
                if(enshow==0&&t<(len-1))
                {
                        if(temp==0)
                        {
                                if(mode&0X80)
                                        LCD_ShowChar(x+(size/2)*t,y,'0',size,mode&0X01);  
                                else
                                        LCD_ShowChar(x+(size/2)*t,y,' ',size,mode&0X01);  
                                continue;
                        }
                        else
                                enshow=1;
                }
                 LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,mode&0X01);
        }
}
//显示字符串
//x,y:起点坐标
//width,height:区域大小  
//size:字体大小
//*p:字符串起始地址                  
void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p)
{         
        u8 x0=x;
        width+=x;
        height+=y;
        while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
        {      
                if(x>=width)
                {
                        x=x0;
                        y+=size;
                }
                if(y>=height)
                        break;//退出
                LCD_ShowChar(x,y,*p,size,0);
                x+=size/2;
                p++;
        }  
}

主控制器较为简单,至此功能基本完成。

使用特权

评论回复
奋斗小范|  楼主 | 2019-6-8 11:49 | 显示全部楼层
本帖最后由 奋斗小范 于 2019-6-8 11:50 编辑

一直这样发不了东西····
QQ截图20190608115007.png

使用特权

评论回复
评论
21ic小喇叭 2019-6-10 11:08 回复TA
@奋斗小范 :OK~~ 
奋斗小范 2019-6-10 11:01 回复TA
@21ic小喇叭 :串口初始化代码里面某些字符,可能认成不良信息了,把那部分删掉就可以了。。。 
21ic小喇叭 2019-6-10 09:11 回复TA
还有类似情况发生吗? 
奋斗小范|  楼主 | 2019-6-8 11:52 | 显示全部楼层
本帖最后由 奋斗小范 于 2019-6-8 12:58 编辑

②从控制器:
工程图片:
27552C6A-DD55-4182-829A-D89707EF98B9.png

初始化:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Init_TIM3(1999,7199);//定时监测主控制器工作情况
Init_TIM4(1666,7199);//LED闪烁控制
Init_USART1(115200);//从控制器状态信息及上位机控制
Init_USART3(115200);//备用
Init_TIM1();//串口解析用
Init_Delay();
Init_IO();
Adc_Init();

主控制器监控:
采用定时对比LED工作状态(灭、3Hz闪烁、常亮)与AD值,若出现问题,则断开主控电源以及与LED的连接。
在调试过程中,一开始只判断一次,经常会出现主控状态判断异常,经排查,是因为在切换控制状态时,采样时间重叠导致错误。
更改为两次判断对比,问题排除。
/********************************************************************************************
*函数名称:TIM3_Init(void)
*入口参数:void
*出口参数:
*功能说明:主控制器监控
*******************************************************************************************/
void Init_TIM3(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef        TIM_TimeBaseStructure;
    NVIC_InitTypeDef        NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

    TIM_TimeBaseStructure.TIM_Period = arr;
    TIM_TimeBaseStructure.TIM_Prescaler =psc;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );

    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    TIM_Cmd(TIM3, ENABLE);
}


定时器3中断服务函数

/********************************************************************************************
*函数名称:TIM3_IRQHandler(void)
*入口参数:void
*出口参数:
*功能说明:定时器3中断服务函数
*******************************************************************************************/
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
if(Led_Count<3)
{
Led_Status[Led_Count]=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);
Led_Count++;
}
else
{
if((Led_Status[0]==1)&&(Led_Status[1]==1)&&(Led_Status[2]==1))
{
if(Adc_Val<1365)
{
Status1=1;
}
else
{
Status1=2;
}
}
else if((Led_Status[0]==0)&&(Led_Status[1]==0)&&(Led_Status[2]==0))
{
if(Adc_Val>=2730)
{
Status1=1;
}
else
{
Status1=2;
}
}
else
{
if((Adc_Val<2730)&&(Adc_Val>=1365))
{
Status1=1;
}
else
{
Status1=2;
}
}
if(Status1==Status2)
{
Work_Status=Status1;
}
Status2=Status1;
Led_Status[0]=0;
Led_Status[1]=0;
Led_Status[2]=0;
Led_Count=0;
}
}
}


使用特权

评论回复
奋斗小范|  楼主 | 2019-6-8 12:38 | 显示全部楼层
本帖最后由 奋斗小范 于 2019-6-8 12:43 编辑

串口信息打印及上位机控制:
目前仅增加远程重启从控制器:
命令(帧头 长度 地址 命令字 校验和 帧尾):7B 06 00 FF 05 7D

/********************************************************************************************
*函数名称:USART1_IRQHandler(void)
*入口参数:
*出口参数:
*功能说明:串口1中断服务程序
*******************************************************************************************/
void USART1_IRQHandler(void)
{
USART1->SR = 0x3df;
SerialBuf[SerialIndex] = USART1->DR;
SerialIndex++;
SerialIndex &= 0x3fu;
TIM1->CNT = 1;
TIM1->SR = 0;
TIM1->CR1 = 0x0d;
}
/********************************************************************************************
*函数名称:Init_TIM1(void)
*入口参数:void
*出口参数:
*功能说明:定时器1初始化
*******************************************************************************************/
void Init_TIM1(void)
{
        TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
        NVIC_InitTypeDef          NVIC_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
        
        TIM_TimeBaseStructure.TIM_Period = 9999; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
        TIM_TimeBaseStructure.TIM_Prescaler = 71; //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
        TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
        NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;  //TIM3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
        TIM_Cmd(TIM1, DISABLE);  //使能TIMx
}
/********************************************************************************************
*函数名称:void TIM1_UP_IRQHandler(void)
*入口参数:
*出口参数:
*功能说明:中断服务函数
********************************************************************************************/
void TIM1_UP_IRQHandler(void)
{
//        printf("ScanMessage\r\n");
        TIM1->SR = 0;
        TIM1->CR1 = 0;
        GetMessage();
        Message_Post(Message[0], Message + 1, MessageLength - 1);
        SerialBuf[0] = 0;
        SerialIndex = 0;
}
/********************************************************************************************
*函数名称:void ScanMessage(void)
*入口参数:
*出口参数:
*功能说明:串口消息解析
********************************************************************************************/
void ScanMessage(void)
{
//        printf("Cmd=%d\r\n",Msg.Cmd);
        switch(Msg.Cmd)
        {
                case 0xFF://重启MCU
                        McuRestart();
                        Msg.Cmd = 0;
                        break;               
                default:
                        break;
        }
}
/********************************************************************************************
*函数名称:void McuRestart(void)
*入口参数:
*出口参数:
*功能说明:MCU复位
********************************************************************************************/
void McuRestart(void)
{
        printf("McuRestart\r\n");
        
        __set_FAULTMASK(1);
        NVIC_SystemReset();
}
从控制器工作截图:
551.jpg

至此从控制器基本完成,下一步进行两控制器联调。

使用特权

评论回复
奋斗小范|  楼主 | 2019-6-8 20:50 | 显示全部楼层
做完基本功能以后,要不要对接一下阿里云呢?

使用特权

评论回复
奋斗小范|  楼主 | 2019-6-9 18:29 | 显示全部楼层
本帖最后由 奋斗小范 于 2019-6-28 14:58 编辑

③主从控制器联调。联调过程基本按预期进行,中间出过小插曲,结果是因为接错线导致。。。。。。

主控制器视频:

从控制器视频:


视频主要展示以下功能:主控制器:
1、ADC采样与LED控制。
2、LCD显示AD值及所处档位。
3、LCD显示LED当前状态。
从控制器:
1、主控制器异常时,从控制器1秒内断开主控电源,并接管控制。
2、串口上传当前AD值、LED状态及主控制器当前状态(正常/异常)。
3、通过命令重启从控制器,此时主控上电,五秒后检测主控工作是否正常。

在看加分项目时发现,程序未按照要求3做(

通过外部调试器或者按键输入使得主控制器能完成控制功能, 但与预先设定的不一样

),待修改。

更改:
之前与题目不符的地方已完成修改。
增加按键控制LED状态:
KEY1:恢复规则控制。
KEY2:停止规则控制,LED常亮。
KEY2:停止规则控制,LED灭。



使用特权

评论回复
奋斗小范|  楼主 | 2019-6-10 12:58 | 显示全部楼层
准备开始对接阿里云,因第一次接触阿里云,需要一边学习一边进行

使用特权

评论回复
iDiy| | 2019-6-10 13:04 | 显示全部楼层
不错哦

使用特权

评论回复
奋斗小范|  楼主 | 2019-6-11 10:23 | 显示全部楼层
本帖最后由 奋斗小范 于 2019-6-11 12:02 编辑

阿里云官方资料:

IOT 学习路径图
https://help.aliyun.com/learn/learningpath/iot.html?source=5176.11533457&userCode=untns54e&type=copy

创建产品与设备_快速入门_阿里云物联网平台-阿里云
https://help.aliyun.com/document_detail/73705.html?source=5176.11533457&userCode=untns54e&type=copy

WiFi模组已准备好,准备开始进行对接~~~



使用特权

评论回复
奋斗小范|  楼主 | 2019-6-12 13:51 | 显示全部楼层
经过三天的学习加实践,对接阿里云基本完成,细节待完善,今天晚上开始分享学习及调试的过程。
Screenshot_20190612_135052_com.aliyun.iot.living.jpg

使用特权

评论回复
奋斗小范|  楼主 | 2019-6-12 23:17 | 显示全部楼层
本帖最后由 奋斗小范 于 2019-6-12 23:18 编辑

创建产品与设备
https://help.aliyun.com/document_detail/73705.html?source=5176.11533457&userCode=&type=copy

此次设计中我选用了阿里云的飞燕平台。
1、首先创建项目:
222.png

333.png
此处ID以后对接会用到。
2、点击进入此项目,创建新产品。
444.png
我们的节点是STM32+WIFI模组,选好对应选项。
3、增加标准功能及自定义功能。
此处功能自行定义。
666.png
4、设备调试。
首先需要选好使用的WiFi模组。
777.png

选好之后,新增一个测试设备
888.png
激活凭证在后面会用到(三元组)。增加完成后停在此步,先去搞STM32部分。

使用特权

评论回复
lihui567| | 2019-6-13 16:38 | 显示全部楼层
奋斗小范 发表于 2019-6-9 18:29
③主从控制器联调。联调过程基本按预期进行,中间出过小插曲,结果是因为接错线导致。。。。。。

主控制器 ...

对主控制器的监控,电路上是怎么做的,如何判断主控制器的异常呢

使用特权

评论回复
奋斗小范|  楼主 | 2019-6-13 17:45 | 显示全部楼层
lihui567 发表于 2019-6-13 16:38
对主控制器的监控,电路上是怎么做的,如何判断主控制器的异常呢

{E7666EE8-43D1-451F-9761-C64DF01E8E9E}_20190613171952.jpg
使用了最简单的办法,从控制器直接检测LED控制脚电平,当电平变化时记录边沿时间计算出频率,将电位器的AD值与LED电平对应,若对应关系不成立,则主控异常。
当然,想要更加严谨,还是需要从外部检测灯的状态,像传感器这种非接触方式。

使用特权

评论回复
评论
奋斗小范 2019-6-14 22:25 回复TA
@zhanzr21 :哈哈,这点误差大部分项目都能接受。 
zhanzr21 2019-6-14 21:58 回复TA
@奋斗小范 :DWT-CYCCNT用这个没有专门定时器精确, 读取这个寄存器的时候有时钟周期的消耗, 还有中断嵌套的因素, 除非做补偿, 不过大多数项目不在乎这个误差. 
奋斗小范 2019-6-14 17:32 回复TA
@lihui567 :中断触发时记录边沿状态(上升/下降沿),同时记录当前DWT->CYCCNT 
奋斗小范 2019-6-14 17:30 回复TA
@lihui567 :习惯使用DWT->CYCCNT,精确且不占定时器。 
lihui567 2019-6-14 14:26 回复TA
通过捕获的方法计算频率,也可以通过测量AD值的方法 
奋斗小范|  楼主 | 2019-6-14 13:49 | 显示全部楼层
不同模组SDK移植方法:


MCU+支持TCP的模组_MCU上集成SDK_移植指南_C SDK_设备接入Link Kit SDK-阿里云
https://help.aliyun.com/document_detail/97921.html?source=5176.11533457&userCode=untns54e&type=copy



MCU+支持MQTT的模组_MCU上集成SDK_移植指南_C SDK_设备接入Link Kit SDK-阿里云
https://help.aliyun.com/document_detail/97922.html?source=5176.11533457&userCode=untns54e&type=copy


使用特权

评论回复
奋斗小范|  楼主 | 2019-6-14 22:37 | 显示全部楼层
本帖最后由 奋斗小范 于 2019-6-14 23:25 编辑

在这说一下为啥对接阿里云。

最初想的是随便做做混一个奖励,原计划从控制器使用串口打印各种状态,做好一看这也太混了,
于是就改成采用局域网的方式将信息打印到网络调试助手上,后来觉得离比赛结束还早,挑战一下自己,
对接一下阿里云,毕竟从没有接触过物联网,在这里有什么不对的地方还请大家多多指教。
既然这次做了,就给他做好!

使用特权

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

本版积分规则

1

主题

66

帖子

1

粉丝