Advertisement
Guest User

Untitled

a guest
Jun 18th, 2019
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 17.94 KB | None | 0 0
  1. #include <app_cfg.h>
  2.  
  3. #include <ucos_ii.h>
  4.  
  5. #include <cpu.h>
  6. #include <lib_def.h>
  7. #include <lib_mem.h>
  8. #include <lib_str.h>
  9. #include "stdbool.h"
  10. #include <bsp.h>
  11.  
  12. #define APP_ASSERT( statement ) do { if(! (statement) ) { __disable_irq(); while(1){ __BKPT(0xAB); if(0) break;} }  } while(0)
  13.  
  14. /***************************************************************************************************
  15.                                  Стеки для тасков
  16.  ***************************************************************************************************/
  17.  
  18. static OS_STK App_TaskStartStack[APP_TASK_START_STACK_SIZE];
  19.  
  20. static OS_STK App_ButtonStack[APP_TASK_BUTTON_STACK_SIZE];
  21.  
  22. static OS_STK App_TaskLed8Stack[APP_TASK_LED8_STACK_SIZE];
  23.  
  24. static OS_STK App_TaskScanKeyboardStack[APP_TASK_KEYBOARD_STACK_SIZE];
  25.  
  26. static OS_STK App_TaskPlaySoundStack[APP_TASK_SOUND_STACK_SIZE];
  27.  
  28. static OS_STK App_TaskSendButtonNumStack[APP_TASK_SEND_BUTTON_NUM_STACK_SIZE];
  29.  
  30. /***************************************************************************************************
  31.                                  Таски - объявления
  32.  ***************************************************************************************************/
  33.  
  34. static void App_TaskStart( void * p_arg );
  35.  
  36. static void App_TaskButton( void * p_arg );// сканирование кнопки PA0
  37.  
  38. static void App_TaskLed8( void * p_arg ); // зажигание светодиода PC8 по нажатию PA0
  39.  
  40. static void App_TaskScanKeyboard( void * p_arg ); // сканирование клавиатуры
  41.  
  42. static void App_TaskPlaySound( void * p_arg ); // играть звук согласно нажатой кнопке
  43.  
  44. static void App_TaskSendButtonNum( void * p_arg ); // отправлять номер нажатой клавиши
  45. //на клавиатуре по USART
  46. OS_EVENT * semaphore;// указатель на семафор
  47. OS_EVENT * queue;// указатель на очередь
  48. #define QUEUE_SIZE 128
  49. static void * queueStorage[ QUEUE_SIZE ]; // массив, в котором будут лежать сообщения
  50.  
  51. int main(void) {
  52.  
  53.     // запрет прерываний и инициализация ОС
  54.     BSP_IntDisAll();
  55.     OSInit();
  56.  
  57.     // создание стартового таска - в нем создаются все остальные
  58.     // почему не создавать всё сразу в main'e?
  59.     // возможно, вы хотите создавать их в зависимости от каких-нибудь условий,
  60.     // для которых уже должна работать ОС
  61.    
  62.     INT8U res = OSTaskCreate(
  63.                     App_TaskStart,     // указатель на таск        
  64.                     NULL,              // параметр вызова (без параметра)
  65.                     &App_TaskStartStack[APP_TASK_START_STACK_SIZE - 1], // указатель на стек
  66.                     APP_TASK_START_PRIO // приоритет
  67.                 );
  68.  
  69.  
  70.    
  71.     APP_ASSERT( res == OS_ERR_NONE );
  72.  
  73.     // запуск многозадачности
  74.     OSStart();
  75.  
  76.     // до сюда выполнение доходить не должно
  77.     return 0;
  78.  
  79. }
  80.  
  81. /***************************************************************************************************
  82.                                  Таски
  83.  ***************************************************************************************************/
  84.  
  85. // стартовый таск
  86. static void App_TaskStart(void * p_arg) {
  87.     // это чтобы убрать warning о неиспользуемом аргументе
  88.     (void)p_arg;
  89.  
  90.     //  Фактически - только настройка RCC - 72 МГц от ФАПЧ  (Initialize BSP functions)
  91.     BSP_Init();
  92.  
  93.     // настройка СисТика
  94.     OS_CPU_SysTickInit();
  95.  
  96.     // таск для сбора статистики - если он нужен                            
  97. #if (OS_TASK_STAT_EN > 0)
  98.     OSStatInit();
  99. #endif
  100.  
  101.     semaphore = OSSemCreate(1); // создание семофора
  102.     queue = OSQCreate( queueStorage, QUEUE_SIZE ); // создание очереди
  103.  
  104.     BSP_IntInit();//для прерываний
  105.  
  106.     // дальше создаются пользовательские таски
  107.    
  108.     INT8U res;
  109.  
  110.     res = OSTaskCreate(
  111.               App_TaskButton, // указатель на функцию      
  112.               NULL,            // параметр - без параметра              
  113.               &App_ButtonStack[APP_TASK_BUTTON_STACK_SIZE - 1], // указатель на массив для стека  
  114.               APP_TASK_BUTTON_PRIO // приоритет
  115.           );
  116.                
  117.     APP_ASSERT( res == OS_ERR_NONE );
  118.  
  119.     res = OSTaskCreate(
  120.               App_TaskLed8,
  121.               NULL,
  122.               &App_TaskLed8Stack[APP_TASK_LED8_STACK_SIZE - 1],
  123.               APP_TASK_LED8_PRIO
  124.           );
  125.                
  126.     APP_ASSERT( res == OS_ERR_NONE );
  127.  
  128.     res = OSTaskCreate(  
  129.               App_TaskScanKeyboard, // указатель на функцию
  130.               NULL, // параметр - без параметра
  131.               &App_TaskScanKeyboardStack[APP_TASK_KEYBOARD_STACK_SIZE - 1], // указатель на массив для стека
  132.               APP_TASK_SCAN_KEYBOARD_PRIO // приоритет
  133.           );
  134.                      
  135.     APP_ASSERT(res == OS_ERR_NONE);
  136.        
  137.     res = OSTaskCreate(
  138.               App_TaskPlaySound, // указатель на функцию
  139.               NULL, // параметр - без параметра
  140.               &App_TaskPlaySoundStack[APP_TASK_SOUND_STACK_SIZE - 1], // указатель на массив для стека
  141.               APP_TASK_PLAY_SOUND_PRIO // приоритет
  142.           );
  143.  
  144.     APP_ASSERT( res == OS_ERR_NONE );
  145.        
  146.     res = OSTaskCreate(
  147.               App_TaskSendButtonNum, // указатель на функцию
  148.               NULL, // параметр - без параметра
  149.               &App_TaskSendButtonNumStack[APP_TASK_SEND_BUTTON_NUM_STACK_SIZE - 1], // указатель на массив для стека
  150.               APP_TASK_SEND_BUTTON_NUM_PRIO // приоритет
  151.           );
  152.  
  153.     APP_ASSERT( res == OS_ERR_NONE );
  154.  
  155.     // этот таск больше не нужен
  156.     OSTaskDel (OS_PRIO_SELF);
  157.                      
  158. }
  159.  
  160. static bool is_button_on = false; // запоминает состояние кнопки PA0
  161.  
  162. // этот таск зажигает светодиод по нажатию кнопки
  163. static void App_TaskLed8( void * p_arg ) {
  164.     // это чтобы убрать warning о неиспользуемом аргументе
  165.     (void)p_arg;
  166.  
  167.     // настройка портов светодиодов и кнопки - делается при первом вызове таска
  168.     // подаем тактирование
  169.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
  170.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
  171.  
  172.     // делаем РС.0 - floating input
  173.     GPIO_InitTypeDef gpioA;
  174.     gpioA.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  175.     gpioA.GPIO_Pin = GPIO_Pin_0;
  176.     gpioA.GPIO_Speed = GPIO_Speed_10MHz;
  177.  
  178.     GPIO_Init( GPIOA, &gpioA );
  179.     // делаем РС.8 - выходом пуш-пулл
  180.     GPIO_InitTypeDef gpioC;
  181.     gpioC.GPIO_Mode = GPIO_Mode_Out_PP;
  182.     gpioC.GPIO_Pin = GPIO_Pin_8;
  183.     gpioC.GPIO_Speed = GPIO_Speed_10MHz;
  184.  
  185.     GPIO_Init( GPIOC, &gpioC );
  186.  
  187.     // таск никогда не должен завершаться через закрывающую скобку
  188.     // поэтому внутри или удаление или бесконечный цикл
  189.     while (1) {
  190.         if (is_button_on == true)
  191.         GPIOC -> ODR |= 1 << 8; // зажечь светодиод при нажатой кнопке
  192.         else GPIOC -> ODR &= ~(1 << 8); // иначе погасить
  193.         // засыпаем на 5 миллисекунд,чтобы поток кнопки захватил управление
  194.         OSTimeDlyHMSM(0, 0, 0, 5);
  195.     }
  196. }
  197.  
  198. // все что делает этот таск - сканирует кнопку
  199. static void App_TaskButton( void * p_arg ) {
  200.     // это чтобы убрать warning о неиспользуемом аргументе
  201.     (void)p_arg;
  202.  
  203.     // настройка портов - делается при первом вызове таска
  204.     // да, в таске для кнопки порты тоже настраиваются - но ведь другой таск может
  205.     // быть и не активен!
  206.  
  207.     // подаем тактирование
  208.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE );
  209.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );
  210.  
  211.     // делаем РС.0 - floating input
  212.     GPIO_InitTypeDef gpioA;
  213.     gpioA.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  214.     gpioA.GPIO_Pin = GPIO_Pin_0;
  215.     gpioA.GPIO_Speed = GPIO_Speed_10MHz;
  216.  
  217.     GPIO_Init( GPIOA, &gpioA );
  218.     // делаем РС.8 - выходом пуш-пулл
  219.     GPIO_InitTypeDef gpioC;
  220.     gpioC.GPIO_Mode = GPIO_Mode_Out_PP;
  221.     gpioC.GPIO_Pin = GPIO_Pin_8;
  222.     gpioC.GPIO_Speed = GPIO_Speed_10MHz;
  223.  
  224.     GPIO_Init( GPIOC, &gpioC );
  225.  
  226.     // таск никогда не должен завершаться через закрывающую скобку
  227.     // поэтому внутри или удаление или бесконечный цикл
  228.     while (1) {
  229.         //если кнопка нажата
  230.         if(((GPIOA->IDR)&1))
  231.         is_button_on = true;
  232.         else is_button_on = false;
  233.         // засыпаем на 5 миллисекунд, чтобы дать время поменять состояние светодиода
  234.         OSTimeDlyHMSM(0, 0, 0, 5);
  235.     }
  236. }
  237.  
  238. static uint8_t button_num = 0;
  239.  
  240. static void App_TaskScanKeyboard(void * p_arg) {
  241.  
  242.     (void) p_arg;
  243.  
  244.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  245.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
  246.     GPIO_InitTypeDef PortA;
  247.     PortA.GPIO_Mode = GPIO_Mode_IPU;
  248.     PortA.GPIO_Pin = (GPIO_Pin_1) | (GPIO_Pin_2) | (GPIO_Pin_3) | (GPIO_Pin_4);
  249.     PortA.GPIO_Speed = GPIO_Speed_50MHz;
  250.     GPIO_Init(GPIOA, &PortA); // строки клавиатуры
  251.  
  252.     GPIO_InitTypeDef PortC;
  253.     PortC.GPIO_Mode = GPIO_Mode_Out_OD;
  254.     PortC.GPIO_Pin = (GPIO_Pin_1) | (GPIO_Pin_2) | (GPIO_Pin_3);
  255.     PortC.GPIO_Speed = GPIO_Speed_50MHz;
  256.     GPIO_Init(GPIOC, &PortC); // столбцы клавиатуры
  257.     GPIO_SetBits(GPIOC, (GPIO_Pin_1) | (GPIO_Pin_2) | (GPIO_Pin_3)); // установим столбцы в 1
  258.  
  259.     while (1) {
  260.         INT8U err;
  261.         OSSemPend(semaphore, 0, &err);
  262.         APP_ASSERT(err == OS_ERR_NONE);
  263.         button_num = 0;
  264.         for (uint8_t cols = 1; cols < 4; cols++) {
  265.             GPIO_ResetBits(GPIOC, 1 << cols); // ставим 0 по очереди по столбцам
  266.             OSTimeDlyHMSM(0, 0, 0, 4); // подождать 4 миллисекунды
  267.         for (uint8_t rows = 1; rows < 5; rows++) { // по очереди проверяем строки
  268.             if (!(GPIOA->IDR&(1 << rows))) {
  269.                 button_num = (cols-1)+3*(rows-1) + 1; // запоминает номер нажатой кнопки, иначе 0
  270.                 break;
  271.                 }
  272.             //GPIOB->ODR ^= 1«10; // apply alternating voltage to the dynamic membrane
  273.             //delay(1000000/(2*ar[(cols-1)+3*(rows-1)]));
  274.             }
  275.         GPIO_SetBits(GPIOC, 1 << cols);
  276.         }
  277.     OSSemPost(semaphore); // освобождение семафора
  278.     OSTimeDlyHMSM(0, 0, 0, 10);
  279.     }
  280. }
  281.  
  282. static void TIM3_IRQHandler() {
  283.     TIM_ClearFlag(TIM3, TIM_IT_Update);
  284.     GPIOB-> ODR ^= 1 << 5;
  285. }
  286.  
  287. static void App_TaskPlaySound(void * p_arg) {
  288.  
  289.     (void)p_arg;
  290.  
  291.     static const uint16_t freq[12] = {600, 800, 1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600,
  292. 2800}; // массив частот в Герцах для каждой из кнопок
  293.  
  294.     RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
  295.     RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  296.  
  297.     TIM_TimeBaseInitTypeDef tim3_struct;
  298.     TIM_TimeBaseStructInit(&tim3_struct);
  299.     tim3_struct.TIM_Period = 100;
  300.     tim3_struct.TIM_CounterMode = TIM_CounterMode_Down;
  301.     TIM_TimeBaseInit(TIM3,&tim3_struct);
  302.  
  303.     TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);//настройка прерываний TIM3
  304.     TIM_Cmd(TIM3,ENABLE);//запуск таймера
  305.     BSP_IntVectSet(BSP_INT_ID_TIM3,TIM3_IRQHandler);//разрешаем прерывания
  306.  
  307.     GPIO_InitTypeDef gpioB; // настройка динамика
  308.     gpioB.GPIO_Mode = GPIO_Mode_Out_PP;
  309.     gpioB.GPIO_Pin = GPIO_Pin_5;
  310.     gpioB.GPIO_Speed = GPIO_Speed_10MHz;
  311.     GPIO_Init(GPIOB, &gpioB);
  312.  
  313.     while(1) {
  314.         INT8U err;
  315.         OSSemPend(semaphore, 0, &err);
  316.         APP_ASSERT(err == OS_ERR_NONE);
  317.         //если кнопка нажата          
  318.         if(button_num) {
  319.             tim3_struct.TIM_Prescaler = (72000000 / (200*freq[button_num - 1]))-1;
  320.             TIM_TimeBaseInit(TIM3,&tim3_struct);
  321.             NVIC_EnableIRQ(TIM3_IRQn);//разрешение прерываний таймера TIM3
  322.             //если ничего не нажато
  323.             } else {
  324.             NVIC_DisableIRQ(TIM3_IRQn);
  325.             GPIO_ResetBits(GPIOB,GPIO_Pin_5);
  326.             }
  327.         OSSemPost(semaphore);
  328.         OSTimeDlyHMSM(0, 0, 0, 10);
  329.         }
  330. }
  331.  
  332. volatile char tx_buffer[16];
  333. static int8_t counter = 0;
  334.  
  335. static void USART1_IRQHandler(void) {
  336.     if(USART_GetITStatus(USART1, USART_IT_TC) == SET){ //прерывание по передаче
  337.     USART_SendData(USART1,tx_buffer[counter++]);
  338.     }
  339.     if (counter > 15) {
  340.     counter = 0;
  341.     USART_ITConfig(USART1, USART_IT_TC, DISABLE);
  342.     }
  343. }
  344.  
  345. static void App_TaskSendButtonNum(void * p_arg) {
  346.  
  347.     (void)p_arg;
  348.  
  349.     char ASCII;//значение кнопки в ASCII
  350.  
  351.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  352.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  353.  
  354.     GPIO_InitTypeDef gpioB;
  355.     gpioB.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  356.     gpioB.GPIO_Pin = GPIO_Pin_7; //настройка ножки RX USART1
  357.  
  358.     gpioB.GPIO_Mode = GPIO_Mode_AF_PP;
  359.     gpioB.GPIO_Pin = GPIO_Pin_6; //настройка ножки TX USART1
  360.  
  361.     gpioB.GPIO_Speed = GPIO_Speed_2MHz;
  362.     GPIO_Init(GPIOB,&gpioB);
  363.  
  364.     USART_InitTypeDef Usart_struct;
  365.     Usart_struct.USART_BaudRate = 57600;
  366.     Usart_struct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  367.     Usart_struct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  368.     Usart_struct.USART_Parity = USART_Parity_No;
  369.     Usart_struct.USART_StopBits = USART_StopBits_1;
  370.     Usart_struct.USART_WordLength = USART_WordLength_8b;
  371.     USART_Init(USART1,&Usart_struct);//настройка режима работы USART
  372.  
  373.     USART_ITConfig(USART1,USART_IT_TC,DISABLE);
  374.     USART_Cmd(USART1, ENABLE);
  375.     BSP_IntVectSet(BSP_INT_ID_USART1,USART1_IRQHandler);//разрешаем прерывания
  376.     NVIC_EnableIRQ(USART1_IRQn);//разрешение прерываний USART1
  377.     while(1) {
  378.         INT8U err;
  379.         OSSemPend( semaphore,0,&err);
  380.         APP_ASSERT(err == OS_ERR_NONE);
  381.         if(button_num) {
  382.             // перевод кнопки в ASCII
  383.             if(button_num==12) ASCII = 35;// #
  384.             if(button_num==11) ASCII = 48;// 0
  385.             if(button_num==10) ASCII = 42;// *
  386.             else if(button_num<10) ASCII = button_num + 0x30;
  387.             tx_buffer[0] = 'p';
  388.             tx_buffer[1] = 'r';
  389.             tx_buffer[2] = 'e';
  390.             tx_buffer[3] = 's';
  391.             tx_buffer[4] = 's';
  392.             tx_buffer[5] = 'e';
  393.             tx_buffer[6] = 'd';
  394.             tx_buffer[7] = ' ';
  395.             tx_buffer[8] = 'b';
  396.             tx_buffer[9] = 'u';
  397.             tx_buffer[10] = 't';
  398.             tx_buffer[11] = 't';
  399.             tx_buffer[12] = 'o';
  400.             tx_buffer[13] = 'n';
  401.             tx_buffer[14] = ' ';
  402.             tx_buffer[15] = ASCII; // место в сообщении, где должен стоять номер кнопки
  403.             USART_ITConfig(USART1, USART_IT_TC, ENABLE);
  404.         }
  405.                
  406.         //если ничего не нажато
  407.         if(!button_num) {
  408.             tx_buffer[0] = 'n';
  409.             tx_buffer[1] = 'o';
  410.             tx_buffer[2] = 't';
  411.             tx_buffer[3] = 'h';
  412.             tx_buffer[4] = 'i';
  413.             tx_buffer[5] = 'n';
  414.             tx_buffer[6] = 'g';
  415.             tx_buffer[7] = ' ';
  416.             tx_buffer[8] = 'p';
  417.             tx_buffer[9] = 'r';
  418.             tx_buffer[10] = 'e';
  419.             tx_buffer[11] = 's';
  420.             tx_buffer[12] = 's';
  421.             tx_buffer[13] = 'e';
  422.             tx_buffer[14] = 'd';
  423.             tx_buffer[15] = ' ';
  424.             USART_ITConfig(USART1, USART_IT_TC, ENABLE);
  425.         }
  426.         counter = 0;
  427.         OSSemPost(semaphore);
  428.         OSTimeDlyHMSM(0, 0, 0, 8);
  429.     }
  430. }
  431.  
  432. #ifdef USE_FULL_ASSERT
  433.  
  434. // эта функция вызывается, если assert_param обнаружил ошибку
  435. void assert_failed(uint8_t * file, uint32_t line) {
  436.     /* User can add his own implementation to report the file name and line number,
  437.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  438.  
  439.     (void)file;
  440.     (void)line;
  441.  
  442.     __disable_irq();
  443.     while(1) {
  444.         // это ассемблерная инструкция "отладчик, стой тут"
  445.         // если вы попали сюда, значит вы ошиблись в параметрах вызова функции из SPL.
  446.         // Смотрите в call stack, чтобы найти ее
  447.         __BKPT(0xAB);
  448.     }
  449. }
  450.  
  451. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement