Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
嵌入式技术综合讨论
rt_thread 可控硅调光器驱动
发布于 2012-09-10 21:53:54 浏览:3704
订阅该版
主要验证rt_thread是否可以用来做可控硅调光器,并且可以说明rt_thread的实时性 硬件平台stm32f207,主时钟为100MHz 采用资源外部中断引脚,作为过零中断使用,定时器2,采用比较器工作模式。 ``` /* * 调光量结构 */ struct dimer_object //占用20个字节 { rt_uint8_t position; //位置 rt_uint8_t line_id; //回路号 rt_uint8_t value; //当前亮度值 0无效,1最大,FF关 rt_uint8_t target_value; //目标亮度值 rt_uint8_t show_value; //调光影子值 rt_uint8_t set_value; //设定默认亮度值 rt_uint8_t max_value; //设定最大亮度值 rt_uint8_t mix_value; //设定最小亮度值 rt_uint8_t direct; //调光运行方向,0,不改变状态,1,渐亮,2渐暗状态,3,渐亮->渐暗->渐亮,4,渐暗->渐亮 rt_uint8_t ver; //保留 rt_uint16_t fade_time; //渐变时间 rt_uint16_t time_count; //单步步长时间计数 rt_uint16_t dim_value; //调光新值,影子值 void *user_data; //其他类型附加 }; typedef struct dimer_object *dimer_object_t; /******************************************************************************* * Function Name : NVIC_Configuration * Description : Configures the used IRQ Channels and sets their priority. * Input : None * Output : None * Return : None *******************************************************************************/ static void NVIC_Configuration(void) { EXTI_InitTypeDef EXTI_InitStructure; /* Configure V_zero EXTI Line to generate an interrupt on falling edge * PC3 */ /* Connect Button EXTI Line to Button GPIO Pin */ SYSCFG_EXTILineConfig(ZERO_PORT_SOURCE, ZERO_PIN_SOURCE); EXTI_InitStructure.EXTI_Line = EXTI_Line10; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;//EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); /* Clear V_zero EXTI line pending bit */ EXTI_ClearITPendingBit(EXTI_Line10); /* Enable the EXTI Interrupt * */ NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable the TIM2 gloabal Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } static void RCC_Configuration(void) { /* Enable GPIOG clocks */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); /* Enable EXTER and GPIOC clocks */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); } /******************************************************************************* * Function Name : dim_tim_init * Description : 配置定时器比较输出模式 :工作在比较模式,1us分频, * Input : TIMx 定时器名称 Prescaler分频参数 :TIMx,2,3,4,5 Prescaler=100,工作在1us单位 :TIMx,1,8 Prescaler=200,工作在1us单位 * Output : None * Return : None *******************************************************************************/ static void dim_tim_init(TIM_TypeDef* TIMx, uint16_t Prescaler) { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = 65535; TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure); /* Prescaler configuration */ TIM_PrescalerConfig(TIMx, Prescaler, TIM_PSCReloadMode_Immediate); /* Output Compare Timing Mode configuration: Channel1 */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing; //输出模式 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR1_Val; TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(TIMx, &TIM_OCInitStructure); TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Disable); //禁止自动重装 /* Output Compare Timing Mode configuration: Channel4 */ TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = CCR4_Val; TIM_OC4Init(TIMx, &TIM_OCInitStructure); TIM_OC4PreloadConfig(TIMx, TIM_OCPreload_Disable); /* TIM Interrupts enable */ if(TIMx == TIM4 ) { TIM_ITConfig(TIMx, TIM_IT_CC1, ENABLE); } else { TIM_ITConfig(TIMx, TIM_IT_CC1 | TIM_IT_CC4, ENABLE); } /* TIMX enable counter */ TIM_Cmd(TIMx, ENABLE); } /******************************************* 函数名称:GPIO_Configuration 功 能:V_zero, lampctrl IO口配置 参 数:无 返 回 值:无 ********************************************/ static void GPIO_Configuration(void) { uint32_t i,j; GPIO_InitTypeDef GPIO_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG,ENABLE); /* Configure ZERO_PHASE pin as input */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Pin = ZERO_PIN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(ZERO_GPIO, &GPIO_InitStructure); } /******************************************* ********************************************/ void rt_hw_ce_init(void) { RCC_Configuration(); GPIO_Configuration(); NVIC_Configuration(); } void hw_dim_tim_init(void) { NVIC_Configuration(); //中断初始化 dim_tim_init(TIM2,50-1); //配置初始化 1us } /******************************************* 函数名称:dim_value_teat 功 能:定时器2调光测试数据 参 数: 返 回 值:无 ********************************************/ uint32_t dim_value_teat(uint16_t *dim_buf) { static uint32_t t = 0; uint32_t j; uint8_t buf[4]; int result; t++; if(t <= 225) { for(j = 0; j < 20; j ++) dim_buf[j] = (t+j)*31; } else if(t >= 275 && t < 500) { for(j = 0; j <20; j ++) dim_buf[j] = (530-t-j)*31; } else if(t >=510) { t =0; } return 18; } static void rt_thread_dim_flash_entry(void* parameter) { uint32_t i,size; uint16_t dim_buf[20],dim_buf_t[20]; uint8_t buf[10]; rt_base_t level; int result; while (1) { size = dim_value_teat(dim_buf); //构建一个调光数据 t_memcpy(dim_buf_t,dim_buf,size); //缓冲数据把dim_buf 转移到dim_buf_t中,可以不使用 if(size != 0) { /* 把dim_buf中的数据从小到大排序,去除重复数据供,定时器比较使用 */ i = dim_value_copy(dim_buf, size); //注意0,0xFFFF情况 /*把最后一个数据补0x0ffff代表结束*/ if(dim_buf[0] != 0x0FFFF) { dim_buf* = 0x0FFFF; } else { i = 0; } /* 数据关中断刷新数据*/ level = rt_hw_interrupt_disable(); Dim_Value_Size = i+1; t_memcpy(Dim_Value_Array,dim_buf,Dim_Value_Size); t_memcpy(Dim_Value_TBuf,dim_buf_t,size); rt_hw_interrupt_enable(level); } rt_thread_delay(2); } } int rt_dim_flash_init(void) { rt_thread_t thread; hw_dim_tim_init(); /* create led1 thread */ thread = rt_thread_create("dim", rt_thread_dim_flash_entry, RT_NULL, 512, 10, 30); if (thread != RT_NULL) rt_thread_startup(thread); return 0; } /********************************************************************************************************** * RT_USING_FINSH **********************************************************************************************************/ #ifdef RT_USING_FINSH #include
void dim_ch_read(void) { struct rt_list_node *n,*tlist; struct card_object_information *information; card_ce_dimer_t dimer; uint32_t i; /* get object information */ information = &card_object_container[Class_Dimmer_CE]; n = &(information->object_list); /* find list head */ tlist = &(information->object_list); /* find list head */ for (n = tlist->next; n != tlist; n = n->next) { dimer = (card_ce_dimer_t)(struct card_object *)rt_list_entry(n, struct card_object, list); rt_kprintf("card no.%d",dimer->dimer_set[0].position); for(i = 0; i < 3; i++) { rt_kprintf("line no:%d,",dimer->dimer_set*.line_id); rt_kprintf("value:%d: ",dimer->dimer_set*.dim_value); } rt_kprintf(" "); } rt_kprintf("the size :%d...",Dim_Value_Size); for(i = 0; i < Dim_Value_Size ; i++) rt_kprintf("%d,",Dim_Value_Array*); rt_kprintf(" "); } FINSH_FUNCTION_EXPORT(dim_ch_read, read dim value.) #endif /******************************************* 函数名称:exti10_isr 功 能:过零外部中断,用于过零点采集 参 数:无 返 回 值:无 ********************************************/ void exti10_isr(void) { Dim_Value_Index = 0; //调光数据表复位 TIM2->CCR4 = 9300; TIM2->CNT = 0; //清计数器4 TIM2->SR = (uint16_t)~TIM_IT_CC1; TIM2->SR = (uint16_t)~TIM_IT_CC4; } /******************************************* 函数名称:tim2_isr 功 能:用于前沿相控调光 参 数: 返 回 值:无 ********************************************/ void tim2_isr(void) { struct rt_list_node *n,*tlist; uint8_t *src; struct card_object_information *information; card_ce_dimer_t dimer; uint32_t i; /* get object information */ information = &card_object_container[Class_Dimmer_CE]; n = &(information->object_list); /* find list head */ tlist = &(information->object_list); /* find list head */ if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET) //比较器1发生中断 { uint16_t __IO dim_ccr1; TIM2->SR = (uint16_t)~TIM_IT_CC1; dim_ccr1 = TIM2->CCR1; Dim_Value_Index++; TIM2->CCR1 = CCR1_Value_Array[Dim_Value_Index]; for (n = tlist->next; n != tlist; n = n->next) { dimer = (card_ce_dimer_t)(struct card_object *)rt_list_entry(n, struct card_object, list); for(i = 0; i < 3; i++) { src = &(dimer->dimer_set*.position); // if(dim_ccr1 == dimer->dimer_set*.dim_value) { card_config[*src][*(src+1)].GPIO_x->BSRRH = card_config[*src][*(src+1)].GPIO_pin; // LIN_IO_SET(io,pin) } } } } if(TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET) //比较器2 9300处发生中断 { uint16_t __IO *dim_value; dim_value = Dim_Value_TBuf; TIM2->SR = (uint16_t)~TIM_IT_CC1; TIM2->SR = (uint16_t)~TIM_IT_CC4; for (n = tlist->next; n != tlist; n = n->next) { dimer = (card_ce_dimer_t)(struct card_object *)rt_list_entry(n, struct card_object, list); for(i = 0; i < 3; i++) { src = &(dimer->dimer_set*.position); card_config[*src][*(src+1)].GPIO_x->BSRRL = card_config[*src][*(src+1)].GPIO_pin; // LIN_IO_RESET(*src,*(src+1)); } dimer->dimer_set*.dim_value = *dim_value; dim_value++; } } t_memcpy(CCR1_Value_Array,Dim_Value_Array,Dim_Value_Size); TIM2->CCR1 = CCR1_Value_Array[0]; TIM2->CCR4 = 0x0FFFF; } } /////////////////////////////////////////////////////// /******************************************* 函数名称:dim_value_copy 功 能:用于刷新调光比较值 参 数:buf,缓冲缓冲值 返 回 值:返回有多少个需要设定的调光值 描 述: ********************************************/ uint32_t dim_value_copy(uint16_t *buf, uint32_t len) { uint32_t i = 0; SelectSort(buf,len&0x0FF); i = deleteRepeatedData(buf,len&0x0FF); return i; } /*************************************************************** *函 数: SelectSort *功 能: 选择法排序,从小到大排序 *参 数: pData 数组起始地址 * Count 数组长度 *返 回 值: PData 数组从小到大排序完成 *说 明: 从数据中选择最小的同第一个值交换, * 在从省下的部分中选择最小的与第二个交换,这样往复下去 ***************************************************************/ void SelectSort(uint16_t* pData, uint32_t size) { register uint16_t iTemp; register uint32_t iPos; uint32_t i,j ; for(i = 0; i < size-1; i++) { iTemp = pData*; iPos = i; for(j = i+1; j < size; j++) { if(pData[j] < iTemp) { iTemp = pData[j]; iPos = j; } } pData[iPos] = pData*; pData* = iTemp; } } /*************************************************************** *函 数: deleteRepeatedData *功 能: 从数组里面删除重复数据 *参 数: pData 数组起始地址 * Count 数组长度 *返 回 值: 现在数组长度 *说 明: 配合排序法使用 * ***************************************************************/ uint32_t deleteRepeatedData(uint16_t *array, const int size) { uint32_t i,j = 0; for (i = 0; i< size; i++) { while ((array* == array[i+1]) && (i < size -1)) { i++; } array[j++] = array*; } return j; } ``` 测试中,定时器2中断处理函数循环比较浪费时间,最糟糕情况下需要15us时间,还需要对整个结构体进行压缩代码,造成中断处理时间比较长,在第一次测试中,TIM2->CCR1的再赋值在整个循环之后操作,测试将近1个小时,出现光源闪烁,说明中断时间超过超过31us,也就是说明有的关中断时间超过16us,而使CCR1赋值后小于TIM2_CNT,造成没有中断成功。分析可能原因后,把TIM2_CCR1赋值提前,即使外部有关中断时间超过16us,也没有关系,等定时器操作结束后,立即再次进入中断,再进行处理,从时间角度上只是延迟了几十us,对亮度影响可以忽略。
查看更多
3
个回答
默认排序
按发布时间排序
baradream
2012-09-10
这家伙很懒,什么也没写!
``` unsigned short Dim_Value_Array[20] = { 0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF, 0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF, 0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF }; unsigned short CCR1_Value_Array[20]= { 0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF, 0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF, 0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF }; unsigned short Dim_Value_TBuf[20]= { 0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF, 0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF, 0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF,0x0FFFF }; ```
aozima
2012-09-10
调网络不抓包,调I2C等时序不上逻辑分析仪,就像电工不用万用表!多用整理的好的文字,比截图更省流量,还能在整理过程中思考。
MARK,有空慢慢看。
撰写答案
登录
注册新账号
关注者
0
被浏览
3.7k
关于作者
baradream
这家伙很懒,什么也没写!
提问
1
回答
1
被采纳
0
关注TA
发私信
相关问题
1
开新板块了! 迅速占领第一帖!
2
有想玩点阵做电子钟的没?手上有屏
3
LED点阵屏硬件保护研究笔记
4
USB相关、Android、Arduino
5
Arduino即将发布ARM平台新产品
6
关于开关电源的同步整流技术
7
rt_thread_wizard使用教程
8
[转]开源如何盈利
9
FM3系列MCU的IO操作笔记。
10
转一个xoolhaha 的寻一起开发的帖子
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
最新文章
1
10年开发后,我后悔坚持的8个技术信仰,不知你踩中几个
2
MCAX-156 ADC测评
3
【FRDM-MCXA156测评】- CherryUSB与hid鼠标设备模仿
4
【FRDM-MCXA156测评】- 硬件SPI模块
5
【NXP-MCXA156】恩智浦A156上的 IIC(硬件) 实践
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
DMA
USB
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
rt-smart
FAL
I2C_IIC
UART
ESP8266
cubemx
WIZnet_W5500
ota在线升级
PWM
BSP
flash
freemodbus
packages_软件包
潘多拉开发板_Pandora
定时器
GD32
ADC
flashDB
编译报错
socket
中断
Debug
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
SFUD
C++_cpp
MicroPython
本月问答贡献
出出啊
1520
个答案
343
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
813
个答案
178
次被采纳
crystal266
553
个答案
162
次被采纳
whj467467222
1222
个答案
149
次被采纳
本月文章贡献
出出啊
1
篇文章
5
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
3
次点赞
crystal266
2
篇文章
1
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
分享
好友
手机
浏览
扫码手机浏览
投诉
建议
回到
底部