你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【方案秀】+ 基于STM32L073的脉冲计数 精华

[复制链接]
jinglixixi 发布时间:2016-4-26 16:28
     在色彩识别仪的设计中,主要是通过脉冲计数的方式来获取色彩值,因此对脉冲计数功能的实现是必不可少的。
在STM32L073开发板的基础上,配以LCD5110液晶显示器即可构造一个简单的脉冲计数器。LCD5110与STM32L073的连接如下表所示:

  
序号
  
名称
连接
作用
1
VCC
3.3V电源
LCD5110供电
2
GND
电源地
LCD5110供电
3
SCE
电源地
片选控制
4
RESET
PC0
复位控制
5
D/C
PC1
数据/指令选择
6
SDIN
PC2
SPI接口数据收发
7
SCLK
PC3
SPI接口时钟输出
8
LED+
3.3V电源
背景光控制

那么外部的计数脉冲如何获得呢?最简单的方法就是使用LCD5110的时钟信号SCLK来提供。
为了实现脉冲计数功能,并将计数值显示到LCD5110上,可在STM32L073RZ-Nucleo例程的TIM_InputCapture 的基础上进行改造来实现,主要的任务是添加LCD5110函数。

为了控制LCD5110各引脚的高低电平,相关的输出引脚定义如下:
  1. #define SetLCD_SCLK_High()     { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_SET);}
  2. #define SetLCD_SCLK_Low()          { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_3, GPIO_PIN_RESET);}

  3. #define SetLCD_SDIN_High()     { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_SET);}
  4. #define SetLCD_SDIN_Low()          { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_2, GPIO_PIN_RESET);}

  5. #define SetLCD_DC_High()            { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_SET);}
  6. #define SetLCD_DC_Low()            { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_1, GPIO_PIN_RESET);}

  7. #define SetLCD_RST_High()          { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_SET);}
  8. #define SetLCD_RST_Low()            { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_0, GPIO_PIN_RESET);}

  9. #define SetS2_High()           { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);}
  10. #define SetS2_Low()                 { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);}

  11. #define SetS3_High()           { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);}
  12. #define SetS3_Low()                 { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);}
复制代码
LCD5110的初始化函数为:
  1. void LCD_Init(void)
  2. {        
  3.         //SCLK--PC.3
  4.     //DIN--PC.2
  5.     //DC--PC.1
  6.     //RST--PC.0
  7.         __HAL_RCC_GPIOC_CLK_ENABLE();
  8.         GPIO_InitTypeDef   GPIO_InitStruct;
  9.         GPIO_InitStruct.Pin = GPIO_PIN_3| GPIO_PIN_2|GPIO_PIN_1| GPIO_PIN_0;
  10.     GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  11.     GPIO_InitStruct.Pull = GPIO_PULLUP;
  12.     GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
  13.     HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  14.         
  15.         SetLCD_RST_Low();   
  16.         delay_1us();
  17.         SetLCD_RST_High();   
  18.         delay_1us();
  19.         delay_1us();
  20.         
  21.         LCD_write_CMD(0x21);
  22.         LCD_write_CMD(0xc0);
  23.         LCD_write_CMD(0x06);
  24.         LCD_write_CMD(0x13);
  25.         LCD_write_CMD(0x20);
  26.         LCD_Clear();           
  27.         LCD_write_CMD(0x0c);        
  28. }
复制代码
所涉及的函数有延时函数delay_1us()和指令输出函数LCD_write_CMD(),具体代码如下:
  1. long int delay_1us(void)
  2. {
  3.         long int count=2;
  4.         while(count--);
  5.         return 0;
  6. }

  7. void LCD_write_CMD(unsigned char com)
  8. {
  9.     unsigned char uci;
  10.     SetLCD_DC_Low();
  11.         for(uci=0;uci<8;uci++)
  12.         {
  13.                 if(com & 0x80)
  14.                 {
  15.                         SetLCD_SDIN_High();
  16.                   }
  17.                 else
  18.                 {
  19.                         SetLCD_SDIN_Low();
  20.                   }
  21.                 SetLCD_SCLK_Low();        
  22.                 com = com << 1;
  23.                 delay_1us();        
  24.                 SetLCD_SCLK_High();
  25.         }
  26. }
复制代码
在LCD5110显示的过程中,离不开清屏函数LCD_Clear()和字符输出函数LCD_write_char()。
清屏函数用到了显示定位函数LCD_set_XY()和数据输出函数LCD_write_Data();
,其的代码如下:
  1. void LCD_Clear(void)
  2. {
  3.         int uii;
  4.         LCD_set_XY(0,0);
  5.         for(uii=0; uii<504; uii++)
  6.         {
  7.                 LCD_write_Data(0x00);
  8.         }
  9. }
复制代码
数据输出函数是通过读取字符库数组来显示字符的,其代码如下:
  1. void LCD_write_char(unsigned char c)
  2. {
  3.     unsigned char line;
  4.     c -= 32;
  5.     for (line=0; line<6; line++)
  6.         {
  7.               LCD_write_Data(font6x8[c][line]);
  8.           }
  9. }
复制代码
字符库数组的结构如下:
  1. unsigned char font6x8[][6] =
  2. {
  3.     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },   // sp
  4.     { 0x00, 0x00, 0x00, 0x2f, 0x00, 0x00 },   // !
  5.     { 0x00, 0x00, 0x07, 0x00, 0x07, 0x00 },   // "
  6.     { 0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14 },    // #
  7.     ... ...

  8.     { 0x00, 0x44, 0x28, 0x10, 0x28, 0x44 },   // x
  9.     { 0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C },   // y
  10.     { 0x00, 0x44, 0x64, 0x54, 0x4C, 0x44 },   // z
  11.     { 0x14, 0x14, 0x14, 0x14, 0x14, 0x14 }    // horiz lines
  12. }
复制代码
主函数的代码为:
  1. int main(void)
  2. {
  3.   HAL_Init();
  4.   /* 配置系统时钟到2 MHz */
  5.   SystemClock_Config();
  6.   /* 配置LED2 */
  7.   BSP_LED_Init(LED2);
  8.   /* 配置 TIM 的外围情况 */
  9.   /*  TIM2 配置: 输入捕捉模式
  10.      外部信号连接到 TIM2 的通道2 引脚为PB.03
  11.      使用上升沿触发,TIM2 的CCR2 用于 计数的频率值  */
  12.   TimHandle.Init.Period      = 0xFFFF;
  13.   TimHandle.Init.Prescaler    = 0;
  14.   TimHandle.Init.ClockDivision  = 0;
  15.   TimHandle.Init.CounterMode  = TIM_COUNTERMODE_UP;
  16.   if(HAL_TIM_IC_Init(&TimHandle) != HAL_OK)
  17.   {
  18.     /* I初始化报错 */
  19.     Error_Handler();
  20.   }
  21.   /* 设置输入捕捉通道2 */
  22.   sICConfig.ICPolarity  = TIM_ICPOLARITY_RISING;
  23.   sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
  24.   sICConfig.ICPrescaler = TIM_ICPSC_DIV1;
  25.   sICConfig.ICFilter    = 0;   
  26.   if(HAL_TIM_IC_ConfigChannel(&TimHandle, &sICConfig, TIM_CHANNEL_2) != HAL_OK)
  27.   {
  28.     /* 配置报错 */
  29.     Error_Handler();
  30.   }
  31.   
  32.   /* 以中断模式启动输入捕捉 */
  33.   if(HAL_TIM_IC_Start_IT(&TimHandle, TIM_CHANNEL_2) != HAL_OK)
  34.   {
  35.     /* 启动报错 */
  36.     Error_Handler();
  37.   }
  38.             LCD_Init();    // LCD5110初始化
  39.             jm();        //  显示界面
  40.         // 设置显示格式
  41.                 LCD_set_XY(0,1);
  42.                 LCD_write_char('C');
  43.                 LCD_write_char('1');
  44.                 LCD_write_char('=');
  45.                 LCD_set_XY(0,2);
  46.                 LCD_write_char('C');
  47.                 LCD_write_char('2');
  48.                 LCD_write_char('=');
  49.                 LCD_set_XY(0,3);
  50.                 LCD_write_char(' ');
  51.                 LCD_write_char('d');
  52.                 LCD_write_char('=');
  53.             LCD_set_XY(0,4);
  54.                 LCD_write_char(' ');
  55.                 LCD_write_char('f');
  56.                 LCD_write_char('=');
  57.   while(1)
  58.   {     //  显示捕捉值
  59.                 LCD_write_number(30,1,uwIC2Value1);
  60.                 LCD_write_number(30,2,uwIC2Value2);
  61.                 LCD_write_number(30,3,uwDiffCapture);
  62.                 LCD_write_number(30,4,uwFrequency);
  63.                 delay_1ms(1000);  // 控制采集数据的显示间隔
  64.   }
  65. }
复制代码
定时捕捉处理函数代码为:
  1. void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
  2. {
  3.   if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
  4.   {
  5.     if(uhCaptureIndex == 0)
  6.     {
  7.       /* 获取第一次捕捉值 */
  8.       uwIC2Value1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
  9.       uhCaptureIndex = 1;
  10. }
  11.     else if(uhCaptureIndex == 1)
  12.     {
  13.       /* 获取第二次捕捉值 */
  14.       uwIC2Value2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
  15.       /* 捕捉计算 */
  16.       if (uwIC2Value2 > uwIC2Value1)
  17.       {
  18.         uwDiffCapture = (uwIC2Value2 - uwIC2Value1);            //  计算差值  
  19.       }
  20.       else if (uwIC2Value2 < uwIC2Value1)
  21.       {
  22.         uwDiffCapture = ((0xFFFF - uwIC2Value1) + uwIC2Value2) + 1; //  超界补偿处理
  23.       }
  24.       else
  25.       {
  26.         /* 假如捕捉值相等,则已达到测量频率的极限 */
  27.         Error_Handler();                                     //  捕捉值相等时报错
  28.       }
  29.       /* 频率计算: 这是一个以APB1Clk为TIM2计时的示例 */      
  30.       uwFrequency = HAL_RCC_GetPCLK1Freq() / uwDiffCapture;
  31.       uhCaptureIndex = 0;
  32.     }
  33.   }
  34. }
复制代码
数据定位显示函数的代码为:
  1. void LCD_write_number(unsigned char X,unsigned char Y,uint32_t dat)
  2. {
  3.                 LCD_set_XY(X,Y);
  4.                 LCD_write_char('C');
  5.                 LCD_write_char('=');
  6.             if(dat>999999) LCD_write_char(dat%10000000/1000000+0x30);
  7.             if(dat>99999) LCD_write_char(dat%1000000/100000+0x30);
  8.                 if(dat>9999) LCD_write_char(dat%100000/10000+0x30);
  9.             if(dat>999) LCD_write_char(dat%10000/1000+0x30);
  10.                 if(dat>99) LCD_write_char(dat%1000/100+0x30);
  11.                 if(dat>9) LCD_write_char(dat%100/10+0x30);
  12.                 LCD_write_char(dat%10+0x30);
  13. }
复制代码


a.png

评分

参与人数 1 ST金币 +20 收起 理由
zero99 + 20

查看全部评分

收藏 5 评论10 发布时间:2016-4-26 16:28

举报

10个回答
df_flying 回答时间:2016-4-26 16:40:16
东西不错哦~
jinglixixi 回答时间:2016-4-26 16:43:17
d与f的值基本不变,c1和c2值是随时递增的,到界后再从零开始计数。
沐紫 回答时间:2016-4-26 16:47:33
谢谢楼主分享
jinglixixi 回答时间:2016-4-26 16:55:32
后续再将TCS3200色彩传感器加进来,依次控制芯片内部的RGB滤色处理来输出RGB的色彩脉冲,以获取RGB色彩值,为RGB到Lab的色彩模式转换提供支持。
埃斯提爱慕 回答时间:2016-4-27 10:53:46
提示: 作者被禁止或删除 内容自动屏蔽
jinglixixi 回答时间:2016-4-27 12:19:06
感谢!      
sxdahss 回答时间:2016-9-27 14:26:21
麻烦楼主把程序工程分享一下
jinglixixi 回答时间:2016-9-28 08:48:08
sxdahss 发表于 2016-9-27 14:26
麻烦楼主把程序工程分享一下

你代码放到STM32L073的相关例程中进行编译即可,我做的主要工作就是为它配上了LCD5110屏的驱动显示等,你试一试就知道了。
sxdahss 回答时间:2016-9-28 09:10:38
jinglixixi 发表于 2016-9-28 08:48
你代码放到STM32L073的相关例程中进行编译即可,我做的主要工作就是为它配上了LCD5110屏的驱动显示等,你 ...

我已经下到了官网的例程,谢谢你
zhangdaijin 回答时间:2016-9-28 09:11:32
谢谢分享

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版