通过Timer0定时中断,以10k频率响应定时中断。但是想改变10k的响应频率。决定用按键和滚轮。
1.按键。
从初始化Timer0程序里找到“// 8K Hz响应
ROM_TimerLoadSet (TIMER0_BASE, TIMER_A,
ROM_SysCtlClockGet() / SAMPLE_FREQUENCY);”;
用CCS手电筒搜索到“ SAMPLE_FREQUENCY”赋值所在位置:
#define TIVA_MAIN_FREQUENCY 80000000 //80MHz tiva主频
#define SAMPLE_FREQUENCY 10000 //10KHz SPWM波的频率
决定改变:
int M; //按键控制M在1到16之间循环
#define SAMPLE_FREQUENCY M * 5000 //5MKHz SPWM波的频率
shengnan Luo:
if (Key1 == 0) {delayNms(10);if (key1 == 0){while(key1 == 1);M = (M++) & 0x0f;} }if (Key2 == 0) {delayNms(10);if (key2 == 0){while(key2 == 1);M = (M--) & 0x00;} }只会C,而且。。。。。按键该怎样去定义也不是很懂。。。想请教下有没有人会的啊?
还有如果我用滚轮去实现,现实吗?
滚轮的程序我找了下:
/** main.c*//** main.c*/#include <stdint.h> #include <stdbool.h> #include "driverlib/adc.h" #include "driverlib/gpio.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "inc/hw_memmap.h" #include "inc/hw_ints.h" #include "LCDDriver.h" #include "inc/hw_gpio.h" enum {LINE_ONE,LINE_TWO,LINE_THREE,LINE_FOUR,LINE_NUM }line_define;//#define CHAR_WIDTH8 #define WORD_WIDTH16#ifndef TARGET_IS_BLIZZARD_RA1 #define TARGET_IS_BLIZZARD_RA1 #endif/**************************************************************** @brief LCD模块按键响应中断 PC7 对应的为按键S1* @param null* @returnnull ***************************************************************/ extern uint8_t VCA_BUTTON_UP_DOWM; char cur_Col = 0; //中断处理子函数 void Int_GPIO_D_Handler(void) {unsigned long ulStatus;// 读取中断状态ulStatus = GPIOIntStatus(GPIO_PORTD_BASE, true);// 清除中断状态GPIOIntClear(GPIO_PORTD_BASE, ulStatus);// 如果KEY的中断状态有效if (ulStatus & GPIO_PIN_7){// 延时约10ms,消除按键抖动SysCtlDelay(10 * (SysCtlClockGet() / 3000));// 等待KEY抬起while (GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_7) == 0x00);// 延时约10ms,消除松键抖动SysCtlDelay(10 * (SysCtlClockGet()/ 3000));//TODO 逻辑处理if(cur_Col < (NUM_CHAR - 1))cur_Col++;}if (ulStatus & GPIO_PIN_6)// 如果KEY的中断状态有效{// 延时约10ms,消除按键抖动SysCtlDelay(10 * (SysCtlClockGet() / 3000));// 等待KEY抬起while (GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_6) == 0x00);// 延时约10ms,消除松键抖动SysCtlDelay(10 * (SysCtlClockGet()/ 3000));//TODO 逻辑处理if(cur_Col > 0)cur_Col--;}} /**************************************************************** @brief初始化ADC获取滚轮电压值*————————| //TIVA| //M4 PE0|<--ADC模数转换信号源 //________| ***************************************************************/ #define ADC_BASEADC0_BASE// 使用ADC0 #define SequenceNum3// 使用序列3 void Init_ADCWheel(){// 使能ADC0外设SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);// 使能外设端口ESysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);// 选择PE0为外部模拟数字转换功能GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_0);// 使能采样序列号为触发处理获取模式ADCSequenceConfigure(ADC_BASE, SequenceNum, ADC_TRIGGER_PROCESSOR, 0);// ADC配置ADCSequenceStepConfigure(ADC_BASE, SequenceNum, 0, ADC_CTL_CH3 | ADC_CTL_IE |ADC_CTL_END);// 使能ADC配置ADCSequenceEnable(ADC_BASE, SequenceNum);// 清除ADC中断标志位ADCIntClear(ADC_BASE, SequenceNum); }/**************************************************************** @brief获取特定ADC的模数转化采样值。* @paramui32BaseADC采样基地址* @paramui32PeripheralADC启动的外设端口* @returnADC采样值 ***************************************************************/ unsigned long ADC_ValueGet(uint32_t ui32Base, uint32_t ui32SequenceNum) {unsigned long value = 0; // 保存ADC采样值uint32_t ADCValue[1];// 触发获取端口采样ADCProcessorTrigger(ui32Base, ui32SequenceNum);//等待采样结束while(!ADCIntStatus(ui32Base, ui32SequenceNum, false)){}// 清除ADC采样中断标志ADCIntClear(ui32Base, ui32SequenceNum);// 读取ADC采样值ADCSequenceDataGet(ui32Base, ui32SequenceNum, ADCValue);value = ADCValue[0];return value; }/************************************************************* @brief对端口C、D进行按键中断初始化* @param none* @param none***********************************************************/ void Init_Int_Key() {HWREG(GPIO_PORTD_BASE+GPIO_O_LOCK)|= GPIO_LOCK_KEY;HWREG(GPIO_PORTD_BASE+GPIO_O_CR)|= (1<<7);HWREG(GPIO_PORTD_BASE+GPIO_O_DEN)&=(~(1<<7));HWREG(GPIO_PORTD_BASE+GPIO_O_PDR)&= (~(1<<7));HWREG(GPIO_PORTD_BASE+GPIO_O_PUR)&= (~(1<<7));HWREG(GPIO_PORTD_BASE+GPIO_O_AFSEL) &=(~(1<<7));// Make PD6/7 an output.SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);GPIODirModeSet(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7, GPIO_DIR_MODE_IN);GPIOPadConfigSet(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7, GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);GPIOIntTypeSet(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7, GPIO_LOW_LEVEL);GPIOIntEnable(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7);IntEnable(INT_GPIOD_TM4C123);IntMasterEnable();GPIOIntClear(GPIO_PORTD_BASE, GPIO_PIN_6 | GPIO_PIN_7); }unsigned char director = 0;// 当前的移动方向int main(void) {uint32_t pui32ADC0Value[1];// 保存ADC采样值unsigned char old_Raw, old_Col;// 保留上一次的位置unsigned char cur_Raw;// 记录光标当前的横坐标,纵坐标cur_Raw = 0;cur_Col = 0;// 设置系统主频SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN| SYSCTL_XTAL_16MHZ);Init_ADCWheel();LCD_Enable();// 使能LCDLCD_Init();// 初始化LCDLCD_ScreenClr();// 清屏Init_Int_Key();while(1){ADCProcessorTrigger(ADC_BASE, SequenceNum);// Wait for conversion to be completed.while(!ADCIntStatus(ADC_BASE, SequenceNum, false)){}// Clear the ADC interrupt flag.ADCIntClear(ADC_BASE, SequenceNum);// Read ADC Value.ADCSequenceDataGet(ADC_BASE, SequenceNum, pui32ADC0Value);unsigned long sample = pui32ADC0Value[0];cur_Raw = (LCD_MAX_COL * sample) / 4096;// 如果光标发生变化则刷新光标位置if(old_Col != cur_Col || old_Raw != cur_Raw){LCD_Draw_Char_8x8(' ', old_Col, old_Raw, LCD_DRAW_NORMAL);LCD_Draw_Char_8x8(' ', cur_Col, cur_Raw, LCD_DRAW_HIGHLIGHT);}// 保存光标及采样值用于下次比较old_Raw = cur_Raw;old_Col = cur_Col;// 系统延时SysCtlDelay(SysCtlClockGet() / 12);} }但是不知道该怎么应用进去!!!!是否应该折算出滚轮所在电压值,然后对应M????
shengnan Luo:
回复 shengnan Luo:
看了艾研例程里产生spwm的程序,打算更改Timer0的响应频率,找到
“ // 8K Hz响应
ROM_TimerLoadSet (TIMER0_BASE, TIMER_A,
ROM_SysCtlClockGet() / SAMPLE_FREQUENCY);”
试着更改SAMPLE_FREQUENCY(原定义为10000),将它与按键S1,S2结合,结果失败了./**************************************************************** @brief LCD模块按键响应中断 PC7 对应的为按键S1* @param null* @returnnull ***************************************************************/ extern uint8_t VCA_BUTTON_UP_DOWM; #define MAX_a16//中断处理子函数 void Int_GPIO_D_Handler(void) {unsigned long ulStatus;// 读取中断状态ulStatus = GPIOIntStatus(GPIO_PORTD_BASE, true);// 清除中断状态GPIOIntClear(GPIO_PORTD_BASE, ulStatus);// 如果KEY的中断状态有效if (ulStatus & GPIO_PIN_7){// 延时约10ms,消除按键抖动SysCtlDelay(10 * (SysCtlClockGet() / 3000));// 等待KEY抬起while (GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_7) == 0x00);// 延时约10ms,消除松键抖动SysCtlDelay(10 * (SysCtlClockGet()/ 3000));//TODO 逻辑处理if(num2 < (MAX_a - 1))num2++;}if (ulStatus & GPIO_PIN_6)// 如果KEY的中断状态有效{// 延时约10ms,消除按键抖动SysCtlDelay(10 * (SysCtlClockGet() / 3000));// 等待KEY抬起while (GPIOPinRead(GPIO_PORTD_BASE, GPIO_PIN_6) == 0x00);// 延时约10ms,消除松键抖动SysCtlDelay(10 * (SysCtlClockGet()/ 3000));//TODO 逻辑处理if(num2 > 0)num2--;}}//float Change_Num(int num1, int num2){// int num1 = 1; // int num2 = 2; // num1 = num2;// return num1;//}之前的:
shengnan Luo:
回复 shengnan Luo:
学会了怎么弄按键和滚轮、、、但是改变不了SAMPLE_FREQUENCY……..输出的波形频率不变。。。。
话说其实没有很明白Timer0的时钟频率怎么设定的,80M/10000=8k,可是实际测出的为10k左右。。。。。是芯片内部有什么地方导致设定的1000减少了么?还是函数问题?
xyz549040622:
回复 shengnan Luo:
TM0的时钟频率不就是主时钟除以TM0的分频值么,你看看库函数,应该有一个函数专门设置这个值的
shengnan Luo:
回复 xyz549040622:
是的,找到了程序中设定的
#define TIVA_MAIN_FREQUENCY 80000000 //80MHz tiva主频
#define SAMPLE_FREQUENCY 10000 //10KHz SPWM波的频率
#define CARRIER_PERIOD_TIME TIVA_MAIN_FREQUENCY / SAMPLE_FREQUENCY // SPWM波的周期
我想改变SAMPLE_FREQUENCY ,使它能随按键变化,而不是每次都手动改动程序。让他SAMPLE_FREQUENCY = N(已经实现了N随按键和滚轮变化)* SPWM_FREQUENCY。
可是没能成功,N在变(显示出来的)可是出来的PWM频率没变。
新手求教~~~~
shengnan Luo:
回复 xyz549040622:
真的很谢谢~~
不过我有想到过这个,也特意看了下,
// 设置PWM生成器和生成周期
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_3, CARRIER_PERIOD_TIME);
// s设置占空比
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_6 | PWM_OUT_7, CARRIER_PERIOD_TIME / 2);
而上面的楼层也提到了CARRIER_PERIOD_TIME = 主频 / SAMPLE_REQUENCY.
在改动的时候仅仅是将SAMPLE_REQUENCY改动了下,使它不为定值,那么按理说应该会影响到最终生成的PWM波啊。。。。
毕竟在我做改动之前,也是只需要更改SAMPLE_REQUENCY的数值(手动更改程序.h中定义的数值)而已,其他的是能传递过去的。
以前学的C和51,对这个刚入门, 是否只改动在main.c中定义 SAMPLE_REQUENCY,并使CARRIER_PERIOD_TIME = 主频 / SAMPLE_REQUENCY是不够的,还得在其他地方修改?
请问我可以加你的Q聊吗?
QQ:1025173868
xyz549040622:
回复 shengnan Luo:
私人qq还是算了吧,有问题在论坛提问就好。看了看你的程序,想法是没错的,但是你的框架搭的有漏洞,外部中断中居然有延时,你需要做的是
1.找准PWM宽度的设置,到底是如何改变的,确保你找的公式正确
2.按键的驱动写好,最好用状态机,或者延时检测完毕,再给一个修改标志
3.写好按键和PWM改变的配合流程。
shengnan Luo:
回复 xyz549040622:
回看了程序,改动后不知为何显示白屏了。
将Timer0在中断中的0A改为了0B,然后又加了上图所示定义,现在做到的仅仅是更改SAMPLE_FREQUENCY,SPWM_FREQUENCY(打算使SAMPLE_FREQUENCY= N * SPWM_FREQUENCY),CARRIER_PERIOD_TIME,同时按比例改变,那么Timer0能出来所想要的频率,
可是一旦写函数,新的SAMPLE_FREQUENCY却没能返回到程序里的SAMPLE_FREQUENCY中去;
求教,到底应该怎样写才能使它能正确地赋值过去、、、、、
PS:有些地方理解地还不是很到位,多多包涵~~~
1.因为不止一个地方用到了SAMPLE_FREQUENCY,所以想的是不动SAMPLE_FREQUENCY所在的地方,只是加一个函数,使其能返回一个新的SAMPLE_FREQUENCY值,这些新的值再赋值给原本用到SAMPLE_FREQUENCY的地方;
2.改变了下按键控制的方式,显示、N值随按键/滚轮变化、PWM频率随定义里的值改变而改变这些都已经做好,所以只剩能正确赋值!
(1)
// 8K Hz响应
ROM_TimerLoadSet (TIMER0_BASE, TIMER_B,
ROM_SysCtlClockGet() / SAMPLE_FREQUENCY);
(2)
// 设置PWM生成器和生成周期
PWMGenPeriodSet(PWM0_BASE, PWM_GEN_3, CARRIER_PERIOD_TIME);
// s设置占空比
PWMPulseWidthSet(PWM0_BASE, PWM_OUT_6 | PWM_OUT_7, CARRIER_PERIOD_TIME / 2);
(3)
ROM_PWMGenPeriodSet (PWM0_BASE, PWM_GEN_3, CARRIER_PERIOD_TIME);
ROM_PWMPulseWidthSet (PWM0_BASE, PWM_OUT_7, SIN_TABLE[SinTable_Index]);
shengnan Luo:
回复 shengnan Luo:
用野蛮的方法使SAMPLE_FREQUENCY随按键的改变而改变了,但是!!!!这样的野蛮方法导致整个.c文件中含有SAMPLE_FREQUENCY只认最前面定义的初始值,而不是变化后的SAMPLE_FREQUENCY!
果然还是得用函数令SAMPLE = N * SPWM,CARRIER_PERIOD_TIME=主频/SAMPLE,然后将新的SAMPLE给到所有涉及到这两个变量的地方。
但是我试了下,仿照程序中原有的程序去做,没能做到新的SAMPLE赋值给原有的3个地方。
又看看了,尝试在Init_Timer0_SPWM那儿加个中断(貌似Gu之前就是这个意思。。。?可惜因为不会写中断,总是偏离方向、、、)