打印

[创新制造展示] 【21ic第三届设计大赛】+冗余执行系统(STM32+阿里云)

[复制链接]
2203|41
跳转到指定楼层
楼主
本帖最后由 奋斗小范 于 2019-7-4 18:07 编辑

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

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


先贴部分硬件图片:



关于此次设计我将分为五部分进行:
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状态显示在触摸屏上。
从控制器在主控制器功能基础上,增加监测功能,监测主控制器输出,在主控制器控制异常时,断开主控制器电源并接管控制,另外从控制器AD值、LED状态与主控制器状态通过串口或者其他方式上传到PC上。

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

评论

zhanzr21 2019-6-5 19:13 回复TA
独立工作的思路很赞, 期待后续资料! 
板凳
 楼主 | 2019-6-6 08:46 | 只看该作者
本帖最后由 奋斗小范 于 2019-6-26 19:19 编辑

2)设计、搭建:

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

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

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

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

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

更改:
从控制器USART3,改为与WiFi模组通讯。
地板
| 2019-6-7 09:37 | 只看该作者
是 类似  这个 图的 功能吗
我们 有 现成的 开发板,一个 MST 可带 99个开发板从站,
很简单就可以与 腾讯云服务器 交换数据


5
 楼主 | 2019-6-7 10:53 | 只看该作者
515192147 发表于 2019-6-7 09:37
是 类似  这个 图的 功能吗
我们 有 现成的 开发板,一个 MST 可带 99个开发板从站,
很简单就可以与 腾讯 ...

不是的,不过感谢你提醒了我,搞完所要求的功能以后,考虑接入云。
6
 楼主 | 2019-6-7 17:17 | 只看该作者
本帖最后由 奋斗小范 于 2019-6-19 10:53 编辑

3)调试流程:
①主控制器:
工程图片:

初始化
  1. delay_init();  
  2. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  3. uart_init(115200);
  4. LED_Init();
  5. KEY_Init();
  6. LCD_Init();
  7. Adc_Init();
  8. TIM3_Init(1666,7199);
  9. W25QXX_Init();//初始化W25Q128
  10. my_mem_init(SRAMIN);//初始化内部内存池
  11. exfuns_init();//为fatfs相关变量申请内存  
  12. f_mount(fs[0],"0:",1);//挂载SD卡
  13. f_mount(fs[1],"1:",1);//挂载FLASH.
  14. LCD_Display_Dir(1);
复制代码

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

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

无法显示汉字,增加字库之后:

ADC初始化:
  1. void  Adc_Init(void)
  2. {         
  3.         ADC_InitTypeDef ADC_InitStructure;
  4.         GPIO_InitTypeDef GPIO_InitStructure;

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

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

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

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

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

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

  14.         NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  15.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  16.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  17.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  18.         NVIC_Init(&NVIC_InitStructure);

  19.         TIM_Cmd(TIM3, DISABLE);
  20. }
复制代码
通过AD采样值控制LED状态:
  1. if(Adc_Val<1365)
  2. {
  3.     TIM_Cmd(TIM3, DISABLE);
  4.     LED2=1;
  5.     LCD_Fill(502,177,673,353,WHITE);
  6. }
  7. else if(Adc_Val<2730)
  8. {
  9.     TIM_Cmd(TIM3, ENABLE);
  10. }
  11. else
  12. {
  13.     TIM_Cmd(TIM3, DISABLE);
  14.     LED2=0;
  15.     LCD_Fill(502,177,673,353,GREEN);
  16. }
复制代码
LCD初始化及驱动代码:
  1. //LCD的画笔颜色和背景色          
  2. u16 POINT_COLOR=0x0000;        //画笔颜色
  3. u16 BACK_COLOR=0xFFFF;  //背景色
  4.   
  5. //管理LCD重要参数
  6. //默认为竖屏
  7. _lcd_dev lcddev;
  8.          
  9. //写寄存器函数
  10. //regval:寄存器值
  11. void LCD_WR_REG(u16 regval)
  12. {   
  13.         LCD->LCD_REG=regval;//写入要写的寄存器序号         
  14. }
  15. //写LCD数据
  16. //data:要写入的值
  17. void LCD_WR_DATA(u16 data)
  18. {         
  19.         LCD->LCD_RAM=data;                 
  20. }
  21. //读LCD数据
  22. //返回值:读到的值
  23. u16 LCD_RD_DATA(void)
  24. {
  25.         vu16 ram;                        //防止被优化
  26.         ram=LCD->LCD_RAM;       
  27.         return ram;         
  28. }                                          
  29. //写寄存器
  30. //LCD_Reg:寄存器地址
  31. //LCD_RegValue:要写入的数据
  32. void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue)
  33. {       
  34.         LCD->LCD_REG = LCD_Reg;
  35.         LCD->LCD_RAM = LCD_RegValue;         
  36. }          
  37. //读寄存器
  38. //LCD_Reg:寄存器地址
  39. //返回值:读到的数据
  40. u16 LCD_ReadReg(u16 LCD_Reg)
  41. {                                                                                  
  42.         LCD_WR_REG(LCD_Reg);
  43.         delay_us(5);                  
  44.         return LCD_RD_DATA();
  45. }   
  46. //开始写GRAM
  47. void LCD_WriteRAM_Prepare(void)
  48. {
  49.         LCD->LCD_REG=lcddev.wramcmd;          
  50. }         
  51. //LCD写GRAM
  52. //RGB_Code:颜色值
  53. void LCD_WriteRAM(u16 RGB_Code)
  54. {                                                            
  55.         LCD->LCD_RAM = RGB_Code;//写十六位GRAM
  56. }
  57. //从ILI93xx读出的数据为GBR格式,而我们写入的时候为RGB格式。
  58. //通过该函数转换
  59. //c:GBR格式的颜色值
  60. //返回值:RGB格式的颜色值
  61. u16 LCD_BGR2RGB(u16 c)
  62. {
  63.         u16  r,g,b,rgb;   
  64.         b=(c>>0)&0x1f;
  65.         g=(c>>5)&0x3f;
  66.         r=(c>>11)&0x1f;         
  67.         rgb=(b<<11)+(g<<5)+(r<<0);                 
  68.         return(rgb);
  69. }
  70. //当mdk -O1时间优化时需要设置
  71. //延时i
  72. void opt_delay(u8 i)
  73. {
  74.         while(i--);
  75. }
  76. //读取个某点的颜色值         
  77. //x,y:坐标
  78. //返回值:此点的颜色
  79. u16 LCD_ReadPoint(u16 x,u16 y)
  80. {
  81.         u16 r=0,g=0,b=0;
  82.         if(x>=lcddev.width||y>=lcddev.height)
  83.                 return 0;
  84.         LCD_SetCursor(x,y);            
  85.         LCD_WR_REG(0X2E);

  86.         r=LCD_RD_DATA();
  87.         opt_delay(2);          
  88.         r=LCD_RD_DATA();

  89.         opt_delay(2);          
  90.         b=LCD_RD_DATA();
  91.         g=r&0XFF;
  92.         g<<=8;

  93.         return (((r>>11)<<11)|((g>>10)<<5)|(b>>11));
  94. }                         
  95. //LCD开启显示
  96. void LCD_DisplayOn(void)
  97. {                                          
  98.         LCD_WR_REG(0X29);
  99. }         
  100. //LCD关闭显示
  101. void LCD_DisplayOff(void)
  102. {          
  103.         LCD_WR_REG(0X28);
  104. }   
  105. //设置光标位置
  106. //Xpos:横坐标
  107. //Ypos:纵坐标
  108. void LCD_SetCursor(u16 Xpos, u16 Ypos)
  109. {         
  110.         LCD_WR_REG(lcddev.setxcmd);
  111.         LCD_WR_DATA(Xpos>>8);
  112.         LCD_WR_DATA(Xpos&0XFF);                          
  113.         LCD_WR_REG(lcddev.setycmd);
  114.         LCD_WR_DATA(Ypos>>8);
  115.         LCD_WR_DATA(Ypos&0XFF);                

  116. }                  
  117. //设置LCD的自动扫描方向           
  118. void LCD_Scan_Dir(u8 dir)
  119. {
  120.         u16 regval=0;
  121.         u16 dirreg=0;
  122.         u16 temp;  
  123.         switch(dir)
  124.         {
  125.                 case L2R_U2D://从左到右,从上到下
  126.                         regval|=(0<<7)|(0<<6)|(0<<5);
  127.                         break;
  128.                 case L2R_D2U://从左到右,从下到上
  129.                         regval|=(1<<7)|(0<<6)|(0<<5);
  130.                         break;
  131.                 case R2L_U2D://从右到左,从上到下
  132.                         regval|=(0<<7)|(1<<6)|(0<<5);
  133.                         break;
  134.                 case R2L_D2U://从右到左,从下到上
  135.                         regval|=(1<<7)|(1<<6)|(0<<5);
  136.                         break;         
  137.                 case U2D_L2R://从上到下,从左到右
  138.                         regval|=(0<<7)|(0<<6)|(1<<5);
  139.                         break;
  140.                 case U2D_R2L://从上到下,从右到左
  141.                         regval|=(0<<7)|(1<<6)|(1<<5);
  142.                         break;
  143.                 case D2U_L2R://从下到上,从左到右
  144.                         regval|=(1<<7)|(0<<6)|(1<<5);
  145.                         break;
  146.                 case D2U_R2L://从下到上,从右到左
  147.                         regval|=(1<<7)|(1<<6)|(1<<5);
  148.                         break;         
  149.         }
  150.         dirreg=0X36;
  151.         LCD_WriteReg(dirreg,regval);

  152.         if(regval&0X20)
  153.         {
  154.                 if(lcddev.width<lcddev.height)//交换X,Y
  155.                 {
  156.                         temp=lcddev.width;
  157.                         lcddev.width=lcddev.height;
  158.                         lcddev.height=temp;
  159.                 }
  160.         }
  161.         else  
  162.         {
  163.                 if(lcddev.width>lcddev.height)//交换X,Y
  164.                 {
  165.                         temp=lcddev.width;
  166.                         lcddev.width=lcddev.height;
  167.                         lcddev.height=temp;
  168.                 }
  169.         }  
  170.         LCD_WR_REG(lcddev.setxcmd);
  171.         LCD_WR_DATA(0);LCD_WR_DATA(0);
  172.         LCD_WR_DATA((lcddev.width-1)>>8);
  173.         LCD_WR_DATA((lcddev.width-1)&0XFF);
  174.         LCD_WR_REG(lcddev.setycmd);
  175.         LCD_WR_DATA(0);LCD_WR_DATA(0);
  176.         LCD_WR_DATA((lcddev.height-1)>>8);
  177.         LCD_WR_DATA((lcddev.height-1)&0XFF);  
  178. }     
  179. //画点
  180. //x,y:坐标
  181. //POINT_COLOR:此点的颜色
  182. void LCD_DrawPoint(u16 x,u16 y)
  183. {
  184.         LCD_SetCursor(x,y);
  185.         LCD_WriteRAM_Prepare();
  186.         LCD->LCD_RAM=POINT_COLOR;
  187. }
  188. //快速画点
  189. //x,y:坐标
  190. //color:颜色
  191. void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color)
  192. {          

  193.         LCD_WR_REG(lcddev.setxcmd);
  194.         LCD_WR_DATA(x>>8);
  195.         LCD_WR_DATA(x&0XFF);
  196.         LCD_WR_REG(lcddev.setycmd);
  197.         LCD_WR_DATA(y>>8);
  198.         LCD_WR_DATA(y&0XFF);

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

  214. //设置LCD显示方向
  215. //dir:0,竖屏;1,横屏
  216. void LCD_Display_Dir(u8 dir)
  217. {
  218.         if(dir==0)                        //竖屏
  219.         {
  220.                 lcddev.dir=0;        //竖屏
  221.                 lcddev.width=240;
  222.                 lcddev.height=320;
  223.                 lcddev.wramcmd=0X2C;
  224.                 lcddev.setxcmd=0X2A;
  225.                 lcddev.setycmd=0X2B;           

  226.         }
  227.         else                                 //横屏
  228.         {                                         
  229.                 lcddev.dir=1;
  230.                 lcddev.width=320;
  231.                 lcddev.height=240;
  232.                 lcddev.wramcmd=0X2C;
  233.                 lcddev.setxcmd=0X2A;
  234.                 lcddev.setycmd=0X2B;           
  235.         }
  236.         LCD_Scan_Dir(DFT_SCAN_DIR);        //默认扫描方向
  237. }         
  238. //设置窗口,并自动设置画点坐标到窗口左上角(sx,sy).
  239. //sx,sy:窗口起始坐标(左上角)
  240. //width,height:窗口宽度和高度,必须大于0!!
  241. //窗体大小:width*height.
  242. void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height)
  243. {   
  244.         u8 hsareg,heareg,vsareg,veareg;
  245.         u16 hsaval,heaval,vsaval,veaval;
  246.         u16 twidth,theight;
  247.         twidth=sx+width-1;
  248.         theight=sy+height-1;
  249.         LCD_WR_REG(lcddev.setxcmd);
  250.         LCD_WR_DATA(sx>>8);
  251.         LCD_WR_DATA(sx&0XFF);         
  252.         LCD_WR_DATA(twidth>>8);
  253.         LCD_WR_DATA(twidth&0XFF);  
  254.         LCD_WR_REG(lcddev.setycmd);
  255.         LCD_WR_DATA(sy>>8);
  256.         LCD_WR_DATA(sy&0XFF);
  257.         LCD_WR_DATA(theight>>8);
  258.         LCD_WR_DATA(theight&0XFF);
  259. }
  260. //初始化lcd
  261. //该初始化函数可以初始化各种ILI93XX液晶,但是其他函数是基于ILI9320的!!!
  262. //在其他型号的驱动芯片上没有测试!
  263. void LCD_Init(void)
  264. {                                        
  265.         GPIO_InitTypeDef GPIO_InitStructure;
  266.         FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
  267.   FSMC_NORSRAMTimingInitTypeDef  readWriteTiming;
  268.         FSMC_NORSRAMTimingInitTypeDef  writeTiming;
  269.        
  270.   RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE);        //使能FSMC时钟
  271.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOE|RCC_APB2Periph_GPIOG,ENABLE);//使能PORTB,D,E,G以及AFIO复用功能时钟


  272.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                                 //PB0 推挽输出 背光
  273.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  //推挽输出
  274.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  275.         GPIO_Init(GPIOB, &GPIO_InitStructure);
  276.        
  277.         //PORTD复用推挽输出  
  278.         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复用推挽输出  
  279.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                  //复用推挽输出   
  280.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  281.         GPIO_Init(GPIOD, &GPIO_InitStructure);
  282.            
  283.         //PORTE复用推挽输出  
  284.         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复用推挽输出  
  285.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;                  //复用推挽输出   
  286.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  287.         GPIO_Init(GPIOE, &GPIO_InitStructure);                                                                                                                  

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

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

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


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

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

  324.         FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);  // 使能BANK1
  325.        
  326.         delay_ms(50);                                         // delay 50 ms

  327.         LCD_WR_REG(0xCF);  
  328.         LCD_WR_DATA(0x00);
  329.         LCD_WR_DATA(0xC1);
  330.         LCD_WR_DATA(0X30);
  331.         LCD_WR_REG(0xED);  
  332.         LCD_WR_DATA(0x64);
  333.         LCD_WR_DATA(0x03);
  334.         LCD_WR_DATA(0X12);
  335.         LCD_WR_DATA(0X81);
  336.         LCD_WR_REG(0xE8);  
  337.         LCD_WR_DATA(0x85);
  338.         LCD_WR_DATA(0x10);
  339.         LCD_WR_DATA(0x7A);
  340.         LCD_WR_REG(0xCB);  
  341.         LCD_WR_DATA(0x39);
  342.         LCD_WR_DATA(0x2C);
  343.         LCD_WR_DATA(0x00);
  344.         LCD_WR_DATA(0x34);
  345.         LCD_WR_DATA(0x02);
  346.         LCD_WR_REG(0xF7);  
  347.         LCD_WR_DATA(0x20);
  348.         LCD_WR_REG(0xEA);  
  349.         LCD_WR_DATA(0x00);
  350.         LCD_WR_DATA(0x00);
  351.         LCD_WR_REG(0xC0);    //Power control
  352.         LCD_WR_DATA(0x1B);   //VRH[5:0]
  353.         LCD_WR_REG(0xC1);    //Power control
  354.         LCD_WR_DATA(0x01);   //SAP[2:0];BT[3:0]
  355.         LCD_WR_REG(0xC5);    //VCM control
  356.         LCD_WR_DATA(0x30);          //3F
  357.         LCD_WR_DATA(0x30);          //3C
  358.         LCD_WR_REG(0xC7);    //VCM control2
  359.         LCD_WR_DATA(0XB7);
  360.         LCD_WR_REG(0x36);    // Memory Access Control
  361.         LCD_WR_DATA(0x48);
  362.         LCD_WR_REG(0x3A);   
  363.         LCD_WR_DATA(0x55);
  364.         LCD_WR_REG(0xB1);   
  365.         LCD_WR_DATA(0x00);   
  366.         LCD_WR_DATA(0x1A);
  367.         LCD_WR_REG(0xB6);    // Display Function Control
  368.         LCD_WR_DATA(0x0A);
  369.         LCD_WR_DATA(0xA2);
  370.         LCD_WR_REG(0xF2);    // 3Gamma Function Disable
  371.         LCD_WR_DATA(0x00);
  372.         LCD_WR_REG(0x26);    //Gamma curve selected
  373.         LCD_WR_DATA(0x01);
  374.         LCD_WR_REG(0xE0);    //Set Gamma
  375.         LCD_WR_DATA(0x0F);
  376.         LCD_WR_DATA(0x2A);
  377.         LCD_WR_DATA(0x28);
  378.         LCD_WR_DATA(0x08);
  379.         LCD_WR_DATA(0x0E);
  380.         LCD_WR_DATA(0x08);
  381.         LCD_WR_DATA(0x54);
  382.         LCD_WR_DATA(0XA9);
  383.         LCD_WR_DATA(0x43);
  384.         LCD_WR_DATA(0x0A);
  385.         LCD_WR_DATA(0x0F);
  386.         LCD_WR_DATA(0x00);
  387.         LCD_WR_DATA(0x00);
  388.         LCD_WR_DATA(0x00);
  389.         LCD_WR_DATA(0x00);                  
  390.         LCD_WR_REG(0XE1);    //Set Gamma
  391.         LCD_WR_DATA(0x00);
  392.         LCD_WR_DATA(0x15);
  393.         LCD_WR_DATA(0x17);
  394.         LCD_WR_DATA(0x07);
  395.         LCD_WR_DATA(0x11);
  396.         LCD_WR_DATA(0x06);
  397.         LCD_WR_DATA(0x2B);
  398.         LCD_WR_DATA(0x56);
  399.         LCD_WR_DATA(0x3C);
  400.         LCD_WR_DATA(0x05);
  401.         LCD_WR_DATA(0x10);
  402.         LCD_WR_DATA(0x0F);
  403.         LCD_WR_DATA(0x3F);
  404.         LCD_WR_DATA(0x3F);
  405.         LCD_WR_DATA(0x0F);
  406.         LCD_WR_REG(0x2B);
  407.         LCD_WR_DATA(0x00);
  408.         LCD_WR_DATA(0x00);
  409.         LCD_WR_DATA(0x01);
  410.         LCD_WR_DATA(0x3f);
  411.         LCD_WR_REG(0x2A);
  412.         LCD_WR_DATA(0x00);
  413.         LCD_WR_DATA(0x00);
  414.         LCD_WR_DATA(0x00);
  415.         LCD_WR_DATA(0xef);         
  416.         LCD_WR_REG(0x11); //Exit Sleep
  417.         delay_ms(120);
  418.         LCD_WR_REG(0x29); //display on       
  419.        
  420.         LCD_Display_Dir(0);                //默认为竖屏
  421.         LCD_LED=1;                                //点亮背光
  422.         LCD_Clear(WHITE);
  423. }  
  424. //清屏函数
  425. //color:要清屏的填充色
  426. void LCD_Clear(u16 color)
  427. {
  428.         u32 index=0;      
  429.         u32 totalpoint=lcddev.width;
  430.         totalpoint*=lcddev.height;                         //得到总点数
  431.         if((lcddev.id==0X6804)&&(lcddev.dir==1))//6804横屏的时候特殊处理  
  432.         {                                                    
  433.                 lcddev.dir=0;         
  434.                 lcddev.setxcmd=0X2A;
  435.                 lcddev.setycmd=0X2B;                                  
  436.                 LCD_SetCursor(0x00,0x0000);                //设置光标位置  
  437.                 lcddev.dir=1;         
  438.           lcddev.setxcmd=0X2B;
  439.                 lcddev.setycmd=0X2A;           
  440.         }
  441.         else
  442.                 LCD_SetCursor(0x00,0x0000);        //设置光标位置
  443.         LCD_WriteRAM_Prepare();                     //开始写入GRAM                   
  444.         for(index=0;index<totalpoint;index++)
  445.         {
  446.                 LCD->LCD_RAM=color;       
  447.         }
  448. }  
  449. //在指定区域内填充单个颜色
  450. //(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)   
  451. //color:要填充的颜色
  452. void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
  453. {         
  454.         u16 i,j;
  455.         u16 xlen=0;
  456.         u16 temp;

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

  465. }  
  466. //在指定区域内填充指定颜色块                         
  467. //(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)   
  468. //color:要填充的颜色
  469. void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color)
  470. {  
  471.         u16 height,width;
  472.         u16 i,j;
  473.         width=ex-sx+1;                         //得到填充的宽度
  474.         height=ey-sy+1;                        //高度
  475.         for(i=0;i<height;i++)
  476.         {
  477.                 LCD_SetCursor(sx,sy+i);           //设置光标位置
  478.                 LCD_WriteRAM_Prepare();     //开始写入GRAM
  479.                 for(j=0;j<width;j++)
  480.                         LCD->LCD_RAM=color[i*width+j];//写入数据
  481.         }                  
  482. }  
  483. //画线
  484. //x1,y1:起点坐标
  485. //x2,y2:终点坐标  
  486. void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
  487. {
  488.         u16 t;
  489.         int xerr=0,yerr=0,delta_x,delta_y,distance;
  490.         int incx,incy,uRow,uCol;
  491.         delta_x=x2-x1; //计算坐标增量
  492.         delta_y=y2-y1;
  493.         uRow=x1;
  494.         uCol=y1;
  495.         if(delta_x>0)
  496.                 incx=1; //设置单步方向
  497.         else if(delta_x==0)
  498.                 incx=0;//垂直线
  499.         else
  500.         {
  501.                 incx=-1;
  502.                 delta_x=-delta_x;
  503.         }
  504.         if(delta_y>0)
  505.                 incy=1;
  506.         else if(delta_y==0)
  507.                 incy=0;//水平线
  508.         else
  509.         {
  510.                 incy=-1;
  511.                 delta_y=-delta_y;
  512.         }
  513.         if( delta_x>delta_y)
  514.                 distance=delta_x; //选取基本增量坐标轴
  515.         else
  516.                 distance=delta_y;
  517.         for(t=0;t<=distance+1;t++ )//画线输出
  518.         {
  519.                 LCD_DrawPoint(uRow,uCol);//画点
  520.                 xerr+=delta_x ;
  521.                 yerr+=delta_y ;
  522.                 if(xerr>distance)
  523.                 {
  524.                         xerr-=distance;
  525.                         uRow+=incx;
  526.                 }
  527.                 if(yerr>distance)
  528.                 {
  529.                         yerr-=distance;
  530.                         uCol+=incy;
  531.                 }
  532.         }  
  533. }   
  534. //画矩形          
  535. //(x1,y1),(x2,y2):矩形的对角坐标
  536. void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)
  537. {
  538.         LCD_DrawLine(x1,y1,x2,y1);
  539.         LCD_DrawLine(x1,y1,x1,y2);
  540.         LCD_DrawLine(x1,y2,x2,y2);
  541.         LCD_DrawLine(x2,y1,x2,y2);
  542. }
  543. //在指定位置画一个指定大小的圆
  544. //(x,y):中心点
  545. //r    :半径
  546. void LCD_Draw_Circle(u16 x0,u16 y0,u8 r)
  547. {
  548.         int a,b;
  549.         int di;
  550.         a=0;b=r;          
  551.         di=3-(r<<1);             //判断下个点位置的标志
  552.         while(a<=b)
  553.         {
  554.                 LCD_DrawPoint(x0+a,y0-b);             //5
  555.                 LCD_DrawPoint(x0+b,y0-a);             //0           
  556.                 LCD_DrawPoint(x0+b,y0+a);             //4               
  557.                 LCD_DrawPoint(x0+a,y0+b);             //6
  558.                 LCD_DrawPoint(x0-a,y0+b);             //1      
  559.                 LCD_DrawPoint(x0-b,y0+a);            
  560.                 LCD_DrawPoint(x0-a,y0-b);             //2            
  561.           LCD_DrawPoint(x0-b,y0-a);             //7                     
  562.                 a++;
  563.                 //使用Bresenham算法画圆     
  564.                 if(di<0)
  565.                         di +=4*a+6;          
  566.                 else
  567.                 {
  568.                         di+=10+4*(a-b);   
  569.                         b--;
  570.                 }                                                     
  571.         }
  572. }                                                                           
  573. //在指定位置显示一个字符
  574. //x,y:起始坐标
  575. //num:要显示的字符:" "--->"~"
  576. //size:字体大小 12/16/24
  577. //mode:叠加方式(1)还是非叠加方式(0)
  578. void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)
  579. {                                                            
  580.   u8 temp,t1,t;
  581.         u16 y0=y;
  582.         u8 csize=(size/8+((size%8)?1:0))*(size/2);                //得到字体一个字符对应点阵集所占的字节数       
  583.         num=num-' ';//得到偏移后的值(ASCII字库是从空格开始取模,所以-' '就是对应字符的字库)
  584.         for(t=0;t<csize;t++)
  585.         {   
  586.                 if(size==12)
  587.                         temp=asc2_1206[num][t];                  //调用1206字体
  588.                 else if(size==16)
  589.                         temp=asc2_1608[num][t];        //调用1608字体
  590.                 else if(size==24)
  591.                         temp=asc2_2412[num][t];        //调用2412字体
  592.                 else
  593.                         return;                                                                //没有的字库
  594.                 for(t1=0;t1<8;t1++)
  595.                 {                            
  596.                         if(temp&0x80)
  597.                                 LCD_Fast_DrawPoint(x,y,POINT_COLOR);
  598.                         else if(mode==0)
  599.                                 LCD_Fast_DrawPoint(x,y,BACK_COLOR);
  600.                         temp<<=1;
  601.                         y++;
  602.                         if(y>=lcddev.height)
  603.                                 return;                //超区域了
  604.                         if((y-y0)==size)
  605.                         {
  606.                                 y=y0;
  607.                                 x++;
  608.                                 if(x>=lcddev.width)
  609.                                         return;        //超区域了
  610.                                 break;
  611.                         }
  612.                 }           
  613.         }                                            
  614. }   
  615. //m^n函数
  616. //返回值:m^n次方.
  617. u32 LCD_Pow(u8 m,u8 n)
  618. {
  619.         u32 result=1;         
  620.         while(n--)
  621.                 result*=m;   
  622.         return result;
  623. }                         
  624. //显示数字,高位为0,则不显示
  625. //x,y :起点坐标         
  626. //len :数字的位数
  627. //size:字体大小
  628. //color:颜色
  629. //num:数值(0~4294967295);         
  630. void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)
  631. {                
  632.         u8 t,temp;
  633.         u8 enshow=0;                                                  
  634.         for(t=0;t<len;t++)
  635.         {
  636.                 temp=(num/LCD_Pow(10,len-t-1))%10;
  637.                 if(enshow==0&&t<(len-1))
  638.                 {
  639.                         if(temp==0)
  640.                         {
  641.                                 LCD_ShowChar(x+(size/2)*t,y,' ',size,0);
  642.                                 continue;
  643.                         }
  644.                         else
  645.                                 enshow=1;
  646.                           
  647.                 }
  648.                  LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,0);
  649.         }
  650. }
  651. //显示数字,高位为0,还是显示
  652. //x,y:起点坐标
  653. //num:数值(0~999999999);         
  654. //len:长度(即要显示的位数)
  655. //size:字体大小
  656. //mode:
  657. //[7]:0,不填充;1,填充0.
  658. //[6:1]:保留
  659. //[0]:0,非叠加显示;1,叠加显示.
  660. void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode)
  661. {  
  662.         u8 t,temp;
  663.         u8 enshow=0;                                                  
  664.         for(t=0;t<len;t++)
  665.         {
  666.                 temp=(num/LCD_Pow(10,len-t-1))%10;
  667.                 if(enshow==0&&t<(len-1))
  668.                 {
  669.                         if(temp==0)
  670.                         {
  671.                                 if(mode&0X80)
  672.                                         LCD_ShowChar(x+(size/2)*t,y,'0',size,mode&0X01);  
  673.                                 else
  674.                                         LCD_ShowChar(x+(size/2)*t,y,' ',size,mode&0X01);  
  675.                                 continue;
  676.                         }
  677.                         else
  678.                                 enshow=1;
  679.                 }
  680.                  LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,mode&0X01);
  681.         }
  682. }
  683. //显示字符串
  684. //x,y:起点坐标
  685. //width,height:区域大小  
  686. //size:字体大小
  687. //*p:字符串起始地址                  
  688. void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p)
  689. {         
  690.         u8 x0=x;
  691.         width+=x;
  692.         height+=y;
  693.         while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
  694.         {      
  695.                 if(x>=width)
  696.                 {
  697.                         x=x0;
  698.                         y+=size;
  699.                 }
  700.                 if(y>=height)
  701.                         break;//退出
  702.                 LCD_ShowChar(x,y,*p,size,0);
  703.                 x+=size/2;
  704.                 p++;
  705.         }  
  706. }
复制代码

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

7
 楼主 | 2019-6-8 11:49 | 只看该作者
本帖最后由 奋斗小范 于 2019-6-8 11:50 编辑

一直这样发不了东西····

评论

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

②从控制器:
工程图片:

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

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

  11.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  12.     TIM_TimeBaseStructure.TIM_Period = arr;
  13.     TIM_TimeBaseStructure.TIM_Prescaler =psc;
  14.     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  15.     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  16.     TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  17.     TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );

  18.     NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  19.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
  20.     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
  21.     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  22.     NVIC_Init(&NVIC_InitStructure);

  23.     TIM_Cmd(TIM3, ENABLE);
  24. }

复制代码

定时器3中断服务函数

  1. /********************************************************************************************
  2. *函数名称:TIM3_IRQHandler(void)
  3. *入口参数:void
  4. *出口参数:
  5. *功能说明:定时器3中断服务函数
  6. *******************************************************************************************/
  7. void TIM3_IRQHandler(void)
  8. {
  9. if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)
  10. {
  11. TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
  12. if(Led_Count<3)
  13. {
  14. Led_Status[Led_Count]=GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);
  15. Led_Count++;
  16. }
  17. else
  18. {
  19. if((Led_Status[0]==1)&&(Led_Status[1]==1)&&(Led_Status[2]==1))
  20. {
  21. if(Adc_Val<1365)
  22. {
  23. Status1=1;
  24. }
  25. else
  26. {
  27. Status1=2;
  28. }
  29. }
  30. else if((Led_Status[0]==0)&&(Led_Status[1]==0)&&(Led_Status[2]==0))
  31. {
  32. if(Adc_Val>=2730)
  33. {
  34. Status1=1;
  35. }
  36. else
  37. {
  38. Status1=2;
  39. }
  40. }
  41. else
  42. {
  43. if((Adc_Val<2730)&&(Adc_Val>=1365))
  44. {
  45. Status1=1;
  46. }
  47. else
  48. {
  49. Status1=2;
  50. }
  51. }
  52. if(Status1==Status2)
  53. {
  54. Work_Status=Status1;
  55. }
  56. Status2=Status1;
  57. Led_Status[0]=0;
  58. Led_Status[1]=0;
  59. Led_Status[2]=0;
  60. Led_Count=0;
  61. }
  62. }
  63. }
复制代码


9
 楼主 | 2019-6-8 12:38 | 只看该作者
本帖最后由 奋斗小范 于 2019-6-8 12:43 编辑

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

  1. /********************************************************************************************
  2. *函数名称:USART1_IRQHandler(void)
  3. *入口参数:
  4. *出口参数:
  5. *功能说明:串口1中断服务程序
  6. *******************************************************************************************/
  7. void USART1_IRQHandler(void)
  8. {
  9. USART1->SR = 0x3df;
  10. SerialBuf[SerialIndex] = USART1->DR;
  11. SerialIndex++;
  12. SerialIndex &= 0x3fu;
  13. TIM1->CNT = 1;
  14. TIM1->SR = 0;
  15. TIM1->CR1 = 0x0d;
  16. }
  17. /********************************************************************************************
  18. *函数名称:Init_TIM1(void)
  19. *入口参数:void
  20. *出口参数:
  21. *功能说明:定时器1初始化
  22. *******************************************************************************************/
  23. void Init_TIM1(void)
  24. {
  25.         TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
  26.         NVIC_InitTypeDef          NVIC_InitStructure;
  27.         RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
  28.         
  29.         TIM_TimeBaseStructure.TIM_Period = 9999; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
  30.         TIM_TimeBaseStructure.TIM_Prescaler = 71; //设置用来作为TIMx时钟频率除数的预分频值
  31.         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
  32.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
  33.         TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位
  34.         TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断
  35.         NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;  //TIM3中断
  36.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
  37.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
  38.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
  39.         NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器
  40.         TIM_Cmd(TIM1, DISABLE);  //使能TIMx
  41. }
  42. /********************************************************************************************
  43. *函数名称:void TIM1_UP_IRQHandler(void)
  44. *入口参数:
  45. *出口参数:
  46. *功能说明:中断服务函数
  47. ********************************************************************************************/
  48. void TIM1_UP_IRQHandler(void)
  49. {
  50. //        printf("ScanMessage\r\n");
  51.         TIM1->SR = 0;
  52.         TIM1->CR1 = 0;
  53.         GetMessage();
  54.         Message_Post(Message[0], Message + 1, MessageLength - 1);
  55.         SerialBuf[0] = 0;
  56.         SerialIndex = 0;
  57. }
  58. /********************************************************************************************
  59. *函数名称:void ScanMessage(void)
  60. *入口参数:
  61. *出口参数:
  62. *功能说明:串口消息解析
  63. ********************************************************************************************/
  64. void ScanMessage(void)
  65. {
  66. //        printf("Cmd=%d\r\n",Msg.Cmd);
  67.         switch(Msg.Cmd)
  68.         {
  69.                 case 0xFF://重启MCU
  70.                         McuRestart();
  71.                         Msg.Cmd = 0;
  72.                         break;               
  73.                 default:
  74.                         break;
  75.         }
  76. }
  77. /********************************************************************************************
  78. *函数名称:void McuRestart(void)
  79. *入口参数:
  80. *出口参数:
  81. *功能说明:MCU复位
  82. ********************************************************************************************/
  83. void McuRestart(void)
  84. {
  85.         printf("McuRestart\r\n");
  86.         
  87.         __set_FAULTMASK(1);
  88.         NVIC_SystemReset();
  89. }
复制代码
从控制器工作截图:

至此从控制器基本完成,下一步进行两控制器联调。
10
 楼主 | 2019-6-8 20:50 | 只看该作者
做完基本功能以后,要不要对接一下阿里云呢?
11
 楼主 | 2019-6-9 18:29 | 只看该作者
本帖最后由 奋斗小范 于 2019-6-28 14:58 编辑

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

主控制器视频:
https://v.youku.com/v_show/id_XNDIyMTQzMTUyOA==.html?spm=a2h3j.8428770.3416059.1
从控制器视频:
https://v.youku.com/v_show/id_XNDIyMTQzMTU0NA==.html?spm=a2h3j.8428770.3416059.1

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

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

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

),待修改。

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



12
 楼主 | 2019-6-10 12:58 | 只看该作者
准备开始对接阿里云,因第一次接触阿里云,需要一边学习一边进行
13
| 2019-6-10 13:04 | 只看该作者
不错哦
14
 楼主 | 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模组已准备好,准备开始进行对接~~~



15
 楼主 | 2019-6-12 13:51 | 只看该作者
经过三天的学习加实践,对接阿里云基本完成,细节待完善,今天晚上开始分享学习及调试的过程。

16
 楼主 | 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、首先创建项目:



此处ID以后对接会用到。
2、点击进入此项目,创建新产品。

我们的节点是STM32+WIFI模组,选好对应选项。
3、增加标准功能及自定义功能。
此处功能自行定义。

4、设备调试。
首先需要选好使用的WiFi模组。


选好之后,新增一个测试设备

激活凭证在后面会用到(三元组)。增加完成后停在此步,先去搞STM32部分。

17
| 2019-6-13 16:38 | 只看该作者
奋斗小范 发表于 2019-6-9 18:29
③主从控制器联调。联调过程基本按预期进行,中间出过小插曲,结果是因为接错线导致。。。。。。

主控制器 ...

对主控制器的监控,电路上是怎么做的,如何判断主控制器的异常呢
18
 楼主 | 2019-6-13 17:45 | 只看该作者
lihui567 发表于 2019-6-13 16:38
对主控制器的监控,电路上是怎么做的,如何判断主控制器的异常呢


使用了最简单的办法,从控制器直接检测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值的方法 
19
 楼主 | 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


20
 楼主 | 2019-6-14 22:37 | 只看该作者
本帖最后由 奋斗小范 于 2019-6-14 23:25 编辑

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

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

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

关闭

热门推荐上一条 /6 下一条

在线客服 快速回复 返回顶部 返回列表